Bienvenue dans ce cours sur le mapping sous le moteur Source de Valve.
Grâce à ce cours, vous pourrez créer vous même vos cartes (vos maps, comme on dit) pour les différents jeux et mods qui reposent sur le moteur Source (HL², CS, TF², Portal...). C'est un cours générique, c'est-à-dire qu'il va vous apprendre à mapper pour le moteur Source, mais pas pour un mod ou un jeu en particulier. Des parties seront consacrées à certaines particularités liées aux mods (comme les bombes de CS, les CP de Team Fortress, les engins de Portal...), mais le cours se focalise avant tout sur le mapping pur et dur :) .
Voici un petit aperçu du monde de Source, avec les plus grands jeux et mods :
Avant de commencer à mapper, il est utile de se procurer les bons outils : le Source SDK ou l'Authoring Tools, si vous désirez mapper pour Left 4 Dead et Portal 2. Voyons un peu de quoi il s'agit !
Valve met à notre disposition un SDK, qui est un ensemble d'outils qui vont nous permettre de créer des maps pour les jeux utilisant le moteur Source. Au début, seul le Source SDK existait. Mais depuis la sortie de Left 4 Dead premier du nom, Valve a décidé de publier des versions ciblées du SDK. Ces versions s'appellent généralement Authoring Tools. Voici les jeux disponibles dans un Authoring Tools :
Left 4 Dead 1 & 2
Portal 2
Alien Swarm
Si vous désirez mapper pour Left 4 Dead il vous faudra télécharger au choix le Left 4 Dead Authoring Tools ou le Left 4 Dead 2 Authoring Tools.
Pour Portal 2, il vous faudra le Portal 2 Authoring Tools. Mais par contre, les outils de création pour Portal premier du nom sont dans le Source SDK.
Pour finir vous voulez mapper pour Alien Swarm, vous devez télécharger l'Alien Swarm - SDK.
Donc, pour récapituler, si vous ne mappez ni pour Left 4 Dead ni pour Portal 2, téléchargez le Source SDK. Pour Left 4 Dead et Portal 2, téléchargez leur Authoring Tools respectif, et si vous mappez pour Alien Swarm, téléchargez le Alien Swarm - SDK.
Installation
Pour installer le SDK, commencez par ouvrir Steam. Dans la fenêtre principale de Steam, allez sous l'onglet Bibliothèque (Library), puis sélectionnez la catégorie Outils (Tools). Double-cliquez sur Source SDK ou un des Authoring Tools, pour lancer le téléchargement, comme s'il s'agissait d'un jeu.
->Téléchargement->
Une fois que c'est fini, toujours dans la catégorie Outils, lancez le SDK, comme si vous lanciez votre jeu préféré.
Le contenu
Les différents SDK, suivant la version choisie
Que vous utilisiez le Source SDK ou un des Authoring Tools, trois logiciels sont présents :
Hammer : C'est le logiciel que nous allons utiliser pour mapper. Son vrai nom est Valve Hammer Editor (ou Valve Hammer World Editor) ;
Model Viewer : C'est un petit logiciel qui permet de visualiser les models. Les models sont des "objets" très détaillés que l'on place dans les maps, comme des armoires, des voitures, des tanks, des pylônes électriques, des portes à poignée... Ce logiciel n'est plus vraiment utile. Il l'était au temps où Hammer ne disposait pas de son propre système de visualisation de models (au tout début du Source SDK) ;
Face Poser : C'est un logiciel dont nous ne parlerons pas car il ne nous sert pas à mapper. C'est une application qui vous permet de définir les animations faciales et les mouvements des personnages dans le cadre de la création d'un mod.
La version du Source Engine, si vous utilisez le Source SDK
Le Source Engine est le moteur graphique créé pour Half-Life². Au fil du temps, ce moteur Source a été mis à jour pour suivre les évolutions de la technologie (ajout de HDR, du support multi-cœur, d'effets en tous genres...). Trois versions majeures du Source Engine sont disponibles, et correspondent à leur année de sortie :
Source Engine 2006 : c'est la première version, celle qui correspond à Half-Life² Deathmatch ;
Source Engine 2007 : plus de jeux ;
Source Engine 2009 : c'est la version qui correspond à Half-Life² ainsi que ses épisodes One et Two. Pour Portal, c'est ici aussi ;
Source Engine MP : c'est la version pour les jeux multijoueurs, c'est-à-dire Counter-Strike: Source, Day Of Defeat: Source et Team Fortress².
Dans le panneau du SDK, choisissez la version de Source à utiliser (Engine Version), en fonction du jeu pour lequel vous allez mapper.
Une fois la version du moteur choisie, sélectionnez le mod pour lequel vous allez mapper (Current Game). Seuls les mods officiels y sont répertoriés.
Pas besoin de configurer le SDK. C'est très pratique, mais le SDK n'est franchement pas le logiciel le plus stable qu'il m'ait été donné de voir. Il est possible que la configuration par défaut soit de temps en temps effacée ou que des bugs apparaissent.
Il se peut aussi que Hammer, et plus généralement le SDK, ne se soit pas configuré par défaut.
Une solution à tous les maux
En cas de problème quelconque, cliquez, dans le panneau d'accueil du SDK, sur Reset Game Configuration, ce qui régénérera une configuration. La fonction Refresh SDK Content peut aussi se révéler salvatrice : elle permet de réactualiser tous les fichiers du SDK, pour en obtenir leur dernière version.
Il se peut aussi qu'à son lancement, Hammer vous dise qu'il n'y a pas de configuration disponible. Pas de panique. Fermez Hammer, le SDK, et lancez le jeu pour lequel vous voulez mapper. Ça actualisera les configurations, et Hammer devrait se lancer sans problème.
Par défaut, le Source SDK est configuré pour être utilisé avec la plupart des jeux officiels. Mais, me direz-vous, il en manque un : Garry's Mod. Je vais donc vous expliquer ici comment ajouter manuellement un jeu pour lequel mapper. Je vais utiliser l'exemple du Garry's Mod.
A propos de Garry's Mod
Garry's Mod est un mod assez particulier dans le sens où il est capable d'afficher le contenu d'autres mods comme Counter-Strike: Source, Day of Defeat: Source, Half-life² Episode Two... La configuration sera donc différente en fonction du contenu que vous allez utiliser, et il va falloir préciser quels contenus utiliser.
Choix de la version du moteur Source
La première étape est le choix de la version du moteur Source. Deux versions majeures existent : le Source Engine 2006 et le 2009. Le 2006 est le moteur Source de base, tandis que celui de 2009 est celui qui correspond à la sortie de l'Orange Box (avec Portal, Team Fortress² et surtout Half-Life² Episode Two). Si vous possédez des jeux utilisant le Source Engine 2009, vous mapperez avec cette version. Si ce n'est pas le cas, vous mapperez avec la version 2006.
Choisissez donc, dans le panneau du Source SDK, le moteur que vous allez utiliser. Moi je prends le 2009. mettez ce que vous voulez pour Current Game, ça n'a pas d'importance.
Lancez Hammer, puis allez dans Tools > Options et dans le premier onglet, cliquez sur Edit. Dans la boîte de dialogue qui s'ouvre, cliquez sur le bouton Add. Saisissez Garry's Mod dans le champ Name :
Cliquez sur OK. Voici maintenant ce que vous devriez avoir dans la boîte d'édition des configurations :
Cliquez sur Close, pour fermer la boîte. Dans la liste déroulante de la fenêtre d'Options, sélectionnez Garry's Mod :
Ajout des FGD
Ensuite, il faut ajouter tous les fichiers .fgd dont nous aurons besoin. Les fichiers FGD sont des fichiers texte, contenant des informations sur les entités. On verra ça en détail plus tard, dans la partie II de ce cours.
Dans le cas de Garry's Mod, pas besoin de télécharger de fichier FGD, on va juste ajouter les fichiers FGD des jeux avec lesquels Garry's Mod est compatible. Un fichier Garrysmod.fgd est présent. Ajoutez donc ces fichiers dans la zone Game data files :
HalfLife2.fgd (ou celui d'HL² Episode 2)
base.fgd
cstrike.fgd
dod.fgd
hl2mp.fgd
portal.fgd
tf.fgd
garrysmod.fgd (se trouve dans le dossier $SteamUserDir\garrysmod\garrysmod (collez cette adresse dans l’explorateur Windows pour y accéder directement))
Textures et entités
Définissez les valeurs de Default Point Entity class et Default SolidEntity class avec respectivement info_player_start et func_detail.
Pour Cordon Texture, mettez tools/toolsskybox.
Sélection des répertoires
Voici les 3 répertoires à utiliser :
Game Executable Directory :$SteamUserDir\garrysmod
Une fois que ceci est fait, validez par le bouton OK, et validez la boite de dialogue :
Fermez Hammer.
Programmes de compilation
Rouvrez Hammer et retournez dans les Options (vérifiez que c'est toujours le mode de jeu Garry's Mod qui est sélectionné). Allez dans l'onglet Build Programs et définissez les chemins comme ceci :
Si vous êtes ici c'est que vous voulez apprendre à créer des maps, c'est-à-dire apprendre à mapper. Mais avant de se lancer dans l'aventure, il est bon de donner quelques informations sur le processus de mapping (création d'une map) ainsi que sur les maps en général.
Tout d'abord une question qui peut paraitre anodine : qu'est-ce qu'une map ?
Une map est un environnement de jeu en 3 dimensions. Cela veut donc dire que le programme que nous allons utiliser, Hammer, est un programme de 3D dont le fonctionnement est similaire à des logiciels de modélisation 3D comme Blender, Maya, 3DSMax... C'est important de le dire, car ce genre de logiciel demande plus de temps d'apprentissage qu'un traitement de texte ou un programme de retouche d'images.
Les étapes de création
Dans un premier temps, nous allons créer un fichier .vmf avec Hammer. Hammer ne travaille d'ailleurs que avec ce format donc vous n'avez pas vraiment le choix. Pour que la map soit jouable, il faudra la compiler, c'est-à-dire convertir le fichier .vmf en un fichier .bsp que le jeu (Half-Life², Left 4 Dead, Counter-Strike...) sera capable de charger. Nous utiliserons aussi Hammer pour compiler.
Quand on crée une map, il est bon de tester fréquemment le résultat, c'est-à-dire de compiler et de tester la map dans le jeu. Tester fréquemment sa map permet de corriger les erreurs rapidement pour éviter de les accumuler. Pour des raisons pratiques, la compilation des maps ne sera abordée que dans la quatrième partie de ce tutoriel. Néanmoins je vous conseille de la lire dès que l'envie vous prend de tester votre début de map (une envie qui viendra assez vite ^^ ).
Chercher de l'aide
Le Source SDK est en anglais, et il n'existe pas de version française, ce qui vous laisse un avant-goût du monde du mapping : quasi tout est en anglais. Il existe bien des sites en français, mais ce n'est jamais vraiment complet. Le meilleur endroit pour vous documenter et chercher des réponses est le Wiki mis en place par Valve. Je vous conseille vivement de vous y référer en cas de problème.
L'environnement de travail est l'espace dans lequel vous allez mapper : c'est Hammer. Vous avez donc lancé Hammer. Allez dans le menu Files puis cliquez sur New, ou faites tout simplement Ctrl+N.
Pour commencer, nous allons un peu analyser les différents composants de l'interface. J'ai numéroté un certain nombre de zones colorées en rouge. L'utilité de ces zones est reprise ci-dessous.
(1)La barre d'outils horizontale : c'est une barre d'outils classique comme on peut en trouver dans la majorité des programmes de bureautique. Elle a pour fonction de mettre à votre disposition toutes sortes de fonctions faciles d'accès. (2)La barre d'outils verticale : cette barre affiche un ensemble d'outils qui nous permettront de mapper. Ils sont indispensables ! Nous y reviendrons plus tard.
(3)Les 4 vues : vue 3D (camera), vue du dessus (top), vue de face (front) et vue de côté (side). Ces 3 dernières vues constituent les vues 2D.
(4)Le panneau des textures : c'est grâce à lui que nous allons pouvoir sélectionner une texture pour un bloc. Ce panneau ne nous sera pas d'une grande utilité, car nous passerons plutôt par un autre panneau (le panneau d'application de textures, que nous ne voyons pas sur l'image).
(5)Le panneau VISGroup : c'est un panneau qui permet de créer des « Groupes de Visibilité ». Ça signifie que vous pouvez rassembler plusieurs objets dans un même groupe, et les masquer, pour ainsi alléger les différentes vues. Nous reviendrons sur ce panneau ultérieurement.
(6)Le panneau de création : ce panneau va nous permettre de sélectionner un type d'entité, de blocs à créer. C'est un peu abstrait. Nous en parlerons dans la prochaine sous-partie.
Les vues 2D
Pour vous expliquer un peu mieux les vues 2D, voici quelques images (elles viennent du tuto de M@teo21 sur le mapping Half-Life 1). M@téo a donc créé un camion et voici les vues 2D :
Le camion vu de dessus (top).
Le camion vu de face (front).
Le camion vu de côté (side).
La vue 3D
La vue 3D est la représentation en 3 dimensions de votre map, c'est-à-dire de vos vues 2D. Elle permet de vous rendre compte de ce que ça donne. La vue 3D possède plusieurs modes d'affichage. Pour y accéder, cliquez sur Camera, en haut à gauche de la fenêtre 3D. Il y a 6 modes d'affichage, mais seulement 3 nous seront utiles : Wireframe, Flat et Textured.
Wireframe n'affiche que les arêtes des blocs de votre map.
Flat affiche votre map, mais sans les textures. Les blocs sont colorés. Ca peut être utile pour repérer des blocs qui dépassent, ou qui posent problème.
Textured affiche tout simplement votre map comment elle sera dans le jeu, mais sans les jeux de lumière. C'est cet affichage-là que nous utiliserons tout le temps.
On n'y trouve pas énormément de choses différentes en fait. On y trouve principalement des blocs, des entités et des displacements. Les entités peuvent servir à insérer d'autres constituants comme des models, des decals et des overlays. Les entités sont de deux types : bloc ou point.
des blocs ;
des displacements ;
des des entités :
des models ;
des decals et des overlays ;
de la lumière, des interactions, des personnages...
Voici une image d ela vue 3D de Hammer, avec différents constituants :
Explications
Les blocs
Une pièce est constituée des blocs : le sol, les murs, le plafond, le chambranle de la porte, et même la vitre. Les blocs (on dit brush en anglais) sont les constituants les plus simples et sont à utiliser pour créer l'architecture de la map. Ils servent à faite le squelette de la map. Les blocs peuvent être convertis en entités point pour leur ajouter des fonctionnalités, comme par exemple créer une plate-forme élévatrice, une vitre cassable, ou un hélice en rotation.
On applique des tetxures sur les faces de blocs
Les models
Dans l'image ci-dessus, on peut apercevoir un radiateur, un moniteur et un néon. Ces trois éléments-là sont des models, c'est-à-dire des éléments en 3D créés à partir d'un logiciel de modélisation comme Blender, XSI ou 3DsMax. Les models sont évidemment plus complexes à créer que des blocs puisqu'ils nécessitent l'utilisation d'un logiciel de modélisation. Les models peuvent être animés (les personnages, comme Alyx, un Terro ou le Soldier de TeamFortress² sont aussi des models). Les models sont partout ! Heureusement, les différents mods possèdent un large éventail de models que vous pourrez utiliser au sein de vos maps.
Voici un screenshot du mod Black Mesa:Source ou l'on peut apercevoir de nombreux models : le shotgun, la rambarde, les néons, les consoles, le boîtier électrique ainsi que le chargeur HEV et le dispenser de soins :
Les models sont aussi des personnages. Voici le rendu d'un Marine dans Black Mesa: Source d'abord non texturé, puis texturé :
Les displacements
Les displacements englobent une technique de création de relief. C'est grâce à eux que vous allez pouvoir créer des décors plus ou moins naturels, comme des montagnes, des rochers arrondis, des trous, des dunes... ou comme dans l'image plus haut, un tas de gravats.
Voici la map pl_upward de Team Fortress². Toute la colline est faite avec des displacements :
Les decals et les overlays
Les decals sont des entités point qui permettent d'apposer une texture sur une autre. On peut les utiliser pour mettre une tâche de sang, des impacts de balles, des panneaux, de la végétation (avec une texture de végétation) sur un mur. Les overlays reposent sur le même principe à la différence près qu'on peu les étirer.
Dans Left 4 Dead, on peut apercevoir de nombreuses affiches placardées un peu partout. Ce sont des decals :
Les entités
Les entités sont des éléments qui possèdent une fonction. Il existe 2 types d'entités : les entités bloc et les entités point. Chaque entité possède un nom et des spécificités différentes. Par exemple, l'entité point prop_static permet d'insérer un model, alors que l'entité point light_spot insère le faisceaux lumineux d'un spot (c'est le "spot" verdâtres dans l'image donné plus haut).
Les entités bloc sont des blocs qui possèdent certaines fonctions. Comme énoncé plus haut, il peut s'agir de plates-formes élévatrices, de vitres cassables... Mais ces entités blocs peuvent aussi être invisibles pour le joueur. C'est le cas d'une zone d'achat dans Counter-Strike par exemple.
Tous ces points seront abordés plus en détail par la suite.
Commencez par créer une nouvelle map, avec Ctrl + N ou via le menu File > New.
Voici les trois outils principaux dont nous allons nous servir :
Cet outil est tout simplement l'outil de sélection. C'est lui qui va nous permettre de sélectionner les différents constituants, dont les blocs ;
Celui-ci, c'est l'outil qui va nous permettre de nous déplacer dans la fenêtre 3D. Son fonctionnement est assez simple : pour avancer ou reculer dans la zone 3D, il suffit d'utiliser la molette de la souris. Laissez le clic gauche enfoncé pour orienter la caméra, et utilisez le clic droit pour effectuer des déplacements latéraux ;
Ça, c'est l'outil de création. C'est lui qui va nous permettre de tracer le contour (en 2D) d'un bloc.
Choix de la texture
Avant de créer un quelconque bloc, il convient de définir la texture dont il sera habillé. Pour cela, dans le panneau des Textures, cliquez sur Browse (Navigation en anglais, qui peut se traduire par Recherche). Une fenêtre s'ouvre alors vous présentant toute une liste de textures.
Heureusement, il existe un système de filtres. Le champ Filtrer va nous permettre de filtrer les textures en fonction d'un ou plusieurs mots-clés. Entrez-y wall par exemple (wall veut dire mur). L'explorateur va alors rechercher toutes les textures de mur. Toutes les textures portent un nom, et dans ce nom figure son type (wall, concrete, metal, wood, floor, nature, citadel...).
Pourquoi ?
Une face en nodraw est une face qui n'est pas affichée et donc qui n'est pas calculée par le moteur Source une fois dans le jeu. Il ne sert donc à rien de lui faire calculer des faces que le joueur ne verra jamais. C'est la raison pour laquelle il est conseillé de créer les blocs avec la texture nodraw et d'ensuite appliquer une texture sur les faces qui seront visibles par le joueur.
Pour sélectionner la texture nodraw, utilisez le filtre. Une fois trouvée, double-cliquez dessus pour la sélectionner et fermer la fenêtre :
Le bloc
Cliquez sur l'outil de création. Placez-vous dans la vue 2D du dessus (top). Cliquez et laissez enfoncé tout en tirant, comme si vous faisiez une sélection dans un logiciel de dessin. Relâchez le bouton.
Votre bloc n'est pas encore créé, ce n'est que son contour qui est fait. Utilisez les poignées de redimensionnement pour modifier sa taille. Modifiez sa taille dans les 2 autres vues 2D. Quand c'est fait, cliquez droit au centre de l'objet, et cliquez sur Create object.
Il se peut aussi que rien n'apparaisse dans la fenêtre 3D. Si c'est le cas, avec l'outil de sélection, cliquez sur le bloc nouvellement créé puis allez dans le menu View et cliquez sur Center 3D Views on Selection. Ce problème peut aussi survenir lors du chargement d'une map (la vue 3D n'affichera rien). Dans ce cas, procédez de la même façon.
Le bloc affiché est noir, je ne vois que les arêtes, pourquoi ?
C'est que la vue 3D n'est pas en Textured. Cliquez sur le petit bouton Camera en haut à gauche de la vue 3D, et sélectionnez Textured.
Quelques astuces
Entraînez-vous à jouer dans la fenêtre 3D : avancez, reculez, tournez... pour vous familiariser ;) Vous pouvez avancer avec les touches W, S, A et D).
Vous pouvez aussi cliquer sur le bouton droit et le bouton gauche en même temps tout en avançant ou en reculant la souris. C'est pratique pour se rapprocher !
Un petit truc bien pratique, dans les vues 2D, est d'enfoncer la touche ESPACE en cliquant. Vous avez ainsi la possibilité de déplacer votre grille.
Pensez aussi à la combinaison Ctrl + E, qui permet de centrer les trois vues 2D sur l'objet sélectionné.
Le combinaison Ctrl + A permet de remettre la taille des quatre vues par défaut.
Vous venez de créer un bloc. Par défaut, ce bloc à la forme d'un parallélépipède rectangle. Mais vous pouvez créer une autre forme, comme un cylindre ou encore une pyramide.
Pour cela, rendez-vous dans le panneau latéral de création, ici :
La liste Objects vous propose la liste des formes géométriques que vous pouvez créer. Suivant la forme choisie, un champ Faces apparaît juste en-dessous. Ce champ vous permet de paramétrer le nombre de faces de votre figure.
Arch : permet de créer une arche. Les options de création d'une arche sont plus complexes, mais vous saurez vous y retrouver assez facilement ;
Block : c'est un bête bloc, la forme géométrique par défaut ;
Cylinder : pour créer un cylindre ;
Sphere : permet de créer une sphère ;
Spike : ça sert à créer des pyramides ;
Torus : c'est un tore, une sorte de beignet creux ^^ ;
Wedge : c'est un triangle en 3D (pas vraiment un triangle donc). On peut appeler ça une cale.
Waw, tu n'es pas très bavard sur tout cela. Pourquoi ?
En effet, et c'est pour une simple raison. Vous vous en sortirez plus facilement avec les blocs simples. Aller faire des sphères et des beignets géants avec des blocs n'est pas vivement recommandé pour des raisons de performances d'affichage. Pour faire des formes arrondies, il vaut mieux utiliser des displacements (que nous verrons par la suite).
Mais un triangle, ça peut être pratique, non ?
Oui, mais pour faire un triangle, je préfère couper un bloc carré en deux. C'est plus simple je trouve (nous verrons comment faire un peu plus loin).
Les vues 2D sont pourvues d’une grille. Celle-ci sert à vous aider à positionner vos blocs et plus tard vos models et vos entités. Par défaut, à l’ouverture de Hammer, la grille est à 64. Vous pouvez voir cette information dans le bas de la fenêtre. C’est l’option intitulée On grid : *nombre*.
Quand la grille est en 64, ça signifie que l’espace entre 2 lignes de la grille vaut 64 unités. Pour vous donner un petit ordre de grandeur, le mur d’un étage d’une maison vaut généralement 128 unités de haut et plus ou moins 16 de large.
Généralement, nous ne travaillerons pas souvent en grille 64. Pour modifier l’unité de la grille, il y a 2 petits boutons dans la barre d’outils horizontale, un + et un - pour augmenter ou diminuer l’unité de la grille :
Le zoom
Toujours dans les vues 2D, vous avez la possibilité de zoomer. Pour zoomer, rien de plus simple : utilisez la molette de votre souris.
Voyons maintenant quelques fonctions utiles pour modifier ce bloc.
Déplacer
Rien de plus simple. Pour déplacer un bloc, cliquez dessus avec l'outil de sélection. Votre curseur devient une croix de déplacement qui va vous permettre de déplacer le bloc.
Redimensionnement
Ça, vous savez comment on fait. Il suffit de prendre l'outil de sélection et de cliquer sur le bloc, aussi bien dans la vue 3D que les vues 2D. Les poignées de redimensionnement apparaissent, et vous n'avez plus qu'à modifier votre bloc.
Rotation
Si vous cliquez une deuxième fois sur un bloc déjà sélectionné, les poignées de redimensionnement disparaissent pour laisser place à des poignées de rotation.
Les 15 degrés
Hammer propose soit une rotation totalement libre, soit une sorte de rotation assistée. Dans la rotation libre, vous faites tourner votre bloc comme bon vous semble. Dans la rotation assistée, vous ne faites tourner votre bloc que par tranche de 15 degrés. Je vous conseille fortement de travailler en 15°.
L'étirement
Pour passer en mode d'étirement, cliquez une troisième fois sur votre bloc. De nouvelles poignées apparaissent. Elles vont vous permettre d'étirer (ou d'incliner) votre bloc.
Sélection multiple
Vous pouvez sélectionner plusieurs objets en appuyant sur la touche Ctrl en même temps que vous cliquez sur les blocs.
Vous pouvez également tracer votre sélection. Pour cela, faites comme si vous créiez un bloc : tracez un rectangle avec l'outil de sélection. Utilisez les vues 2D pour lui faire englober tout ce que vous voulez sélectionner.
Une fois que tout est bien en place, tapez Enter sur votre clavier.
Supprimer
Cliquez sur l'objet que vous souhaitez supprimer, et tapez sur Delete, rien de plus simple ^^
Création homologue
C'est un système de création de bloc assez pratique. Par exemple, vous avez un bloc d'une certaine hauteur, et vous souhaitez créer un autre bloc ayant la même hauteur que celui-là, mais pas la même largeur.
Commencez par cliquer, avec l'outil de sélection, sur le bloc de départ. Hammer, sans rien vous dire, va en quelque sorte retenir les dimensions de ce dernier. Prenez l'outil de création, et dessinez votre bloc dans la vue du dessus (top). Comme par miracle, Hammer assignera au bloc la même hauteur que le bloc précédemment sélectionné. Il n'a évidemment pas la même largeur puisque vous venez de la tracer manuellement dans la vue du dessus (logique ça ^^ )
La duplication
Pour dupliquer, il y a le fameux Copier-coller. Mais je dois dire que ce n'est pas pratique.
Hammer vous propose la duplication par déplacement. Pour cela, sélectionnez, dans une des vues 2D, un bloc. Appuyez sur la touche Majuscule et sur une touche directionnelle (attention, n'appuyez qu'une seule fois). Votre bloc est maintenant dupliqué, et déplacé d'une largeur de grille.
Jusqu'à présent, je vous ai dit de toujours créer vos blocs avec la texture nodraw. C'est très bien, et on va continuer à apprendre de cette façon. Cependant, mettre des textures est essentiel pour créer sa map, si l'on veut jouer un jour dessus !
Pour ce faire, reprenons notre bon vieux bloc carré. Cliquez sur l'outil d'application de textures :
. Une belle nouvelle fenêtre s'ouvre alors avec tout un tas d'options barbares. Cette fenêtre, tant que maintenant, n'a aucune utilité. Remarquez que votre curseur de souris a changé d'aspect :
. Avec ce nouveau curseur, vous allez cliquer sur une face de votre cube :
La face sur laquelle vous avez cliqué devient alors plus foncée : elle est sélectionnée, et les paramètres de cette face s'affichent dans la fenêtre.
Dans la fenêtre, cliquez simplement sur Browse pour rechercher une nouvelle texture à appliquer sur la ou les faces sélectionnées. Une fois la nouvelle texture trouvée et sélectionnée, cliquez sur le bouton Apply.
Options disponibles
Texture scale : c'est l'échelle de la texture. Une valeur de 1 signifie que la texture n'est pas étirée. A 0.25, la texture est étirée négativement, elle est donc plus petite que la normale. Sous le moteur Source, on laissera généralement une scale de 0.25. On passe parfois à 0.5 ou 1 dans le cas de décors lointains.
Texture shift : c'est le décalage de la texture par rapport à sa position d'origine, sur les axes X et Y. Cette option sert à aligner la texture très précisément.
Boutons Justify : ce sont des petites fonctions d'alignement de la texture, qui peuvent remplir automatiquement Texture shift. Cette zone est composée des fonctions suivantes :
L (left - aligner à gauche)
R (right - aligner à droite)
Fit (adapter l'étirement de la texture aux dimensions de la face)
T (top - aligner en haut)
B (bottom - aligner en bas)
C (center - centrer la texture)
World et Face : ce sont deux options un peu spéciales. Généralement, les 2 options sont cochées dans le cas d'une face horizontale ou verticale. Si la face est oblique (un triangle par exemple), une seule sera cochée. Vérifiez bien que 2 faces aient la même option de cochée si les textures refusent de s'aligner. L'option face est en fait une sorte d'effet miroir de la texture, elle est inversée.
Bien sur, Rotation est l'angle d'inclinaison de la texture :)
Entraînez-vous à faire des blocs et à leur appliquer des textures, à les aligner...
Je ne sais pas si vous l'avez remarqué, mais il y a des textures bizarres, quand vous tapez tools dans l'explorateur de textures.
Les textures tools sont des textures qui possèdent une fonction. Quand elles sont appliquées sur un bloc, ce bloc n'est plus considéré comme un simple bloc, il possède une fonction.
Vous remarquerez aussi que la texture nodraw que je vous fais utiliser est une texture spéciale. En effet, dans le jeu, une face de bloc avec cette texture ne sera tout simplement pas affichée, et donc pas calculée par le moteur Source. C'est en fait une technique pour alléger les calculs du moteur. Nous mettons du nodraw SUR TOUTES LES FACES QUE LE JOUEUR NE VOIT PAS. Cette technique est une technique dite d'optimisation. Il y en a plein d'autres, mais celle-ci est la plus élémentaire, et c'est pourquoi il est bon que vous l'adoptiez dès le début :) C'est juste pour vous simplifier la vie que je vous ai dit de créer des blocs directement avec la texture nodraw. Vous n'avez plus qu'à mettre une belle texture sur les faces visibles pour le joueur.
Je vais vous parler ici de quelques autres textures spéciales qui peuvent être utiles. En règle générale, seul nodraw n'a pas besoin d'être appliquée sur toutes les faces d'un bloc. C'est la seule, avec hint et skip.
C'est juste une texture noire. Elle n'est pas affectée par la lumière. C'est utile pour faire le fond d'un couloir qui s'enfonce dans les ténèbres ^^
Cette texture bloque les balles (et le joueur aussi)
Cette texture bloque la lumière
Le bloc est invisible, mais il est aussi physique, le joueur et les objets peuvent butter contre. Très pratique pour empêcher l'accès à une zone quelconque.
Le bloc est invisible, mais il est physique, le joueur peut butter contre. Un bloc avec cette texture peut être utilisé comme entité bloc.
Un bloc avec cette texture est une échelle invisible. Ca ne marche que dans Counter-Strike Source (faire une échelle est plus complexe dans les autres mods).
Bah, je vous en ai déjà parlé ^^
Même utilisation que clip, mais ici, c'est seulement pour les joueurs
C'est une texture que l'on met sur les blocs qui nous serviront à créer des déclencheurs. Par exemple, si le joueur passe dedans, alors, tout explose (je suis sadique, moi ? :D )
Pour mettre du ciel dans une map, on utilise la texture toolsskybox. Un bloc de ciel doit être complètement recouvert de cette texture.
Environnement hermétique
Retenez bien ceci : votre map doit toujours être fermée ! Ça signifie que durant le jeu, le joueur ne doit pas pouvoir apercevoir le noir, le vide. Bien sur, dans une map qui se passe complètement à l'intérieur d'un bâtiment, c'est assez facile de fermer la map.
Dans une map qui se déroule à l'extérieur, on va fermer la map avec des blocs de ciel, c'est-à-dire des blocs avec la texture skybox. Regardez cette image, c'est la map de_cbble fournie avec le SDK :
Comme vous le voyez, le mappeur a fermé la map avec des blocs de ciel :)
Dans le jeu, cette texture sera remplacée par une texture de ciel spéciale.
Donc, votre map doit toujours être fermée. Si vous laissez un trou, même d'une seule unité, la compilation de votre map plantera : on dit alors qu'on a un leak.
La texture de ciel
Dans l'explorateur de textures, recherchez toutes les textures appelées skybox. Les textures de ciel s'appellent toujours comme ceci : skybox/nomface.
Une texture de ciel est en fait un jeu de 6 textures : 4 côtés, le bas, et le dessus. Face est tout simplement une indication de 2 lettres, qui permet de définir sur quelle face sera appliquée la texture. Par exemple, pour le ciel de cs_assault, la texture se nomme skybox/assault (on enlève juste les 2 lettres finales). Donc, finalement, le nom de la texture est simplement assault.
Définir la texture
Pour appliquer la texture de cs_assault sur votre map, c'est très simple. Allez dans le menu Map, puis dans Map properties. Cliquez sur SkyBox Texture Name, et entrez le nom de la texture, c'est-à-dire assault.
Mauvaise technique
Parfois il n'est pas facile de repérer l'endroit où se trouve le leak, et le mappeur fait ce que l'on appelait, sous Half-Life1, une Skybox, c'est-à-dire qu'il englobait la map dans un bloc de ciel vide. C'est évidemment un technique à proscrire, y compris pour Half-Life 1 (mais ça on s'en fout ici ^^ ). C'est très mauvais, car le compilateur de visibilité (vvis) et de luminosité (vrad) va croire que votre map n'est pas finie, et va calculer des endroits que le joueur ne devrait pas voir, ce qui fait énormément de travail inutile.
Quelque chose de très difficile quand on commence à mapper, outre le fait de devoir prendre en main Hammer, est de s'y retrouver dans les dimensions. Je me souviens de mon premier test, du temps d'Half-Life 1. J'avais fait une petite maison, et les marches de l'escalier étaient si hautes que je ne savais pas les monter ^^ .
Si vous joué à Day Of Defeat, Team Fortress³ ou Counter-Strike, vous avez certainement déjà croisé des maps dites "orange", caractérisées par des textures orange. Outre le fait que ce soit laid, ne nous êtes-vous jamais demandé pourquoi le jeu incluait des textures orange ?
Eh bien ces textures sont en fait des textures de développement, dites "textures de dev". Certaines textures de dev présentent des indications qui aident le mappeur à s'y retrouver dans les dimensions. C'est ce que nous allons voir maintenant.
Les textures de base
Il y a deux textures de bases principales, qui sont souvent utilisées dans les maps orange :
dev_blendmeasure : texture carrée grise, à utiliser pour le sol
dev_measuregeneric01 : texture orange de base, à utiliser pour les murs et certains revêtements ne demandant pas de mesures précises
Les murs
128, le standard
Sous la quasi-totalité des jeux Source, un mur d'un étage fait 128 unités de haut. La texture dev_measurewall01a est une texture carrée de 128*128 que vous pouvez utiliser pour texturer vos murs. Le truc pratique c'est que les vrais textures de mur font aussi 128*128 comme grandeur (parfois le double), autrement dit ça vous donne une bonne idée du rendu de votre mur.
Les caisses
D'autres textures peuvent servir de mesure, notamment les textures dev de caisses . Voici les 4 principales :
64*64 : dev_measurecrate01 : un demi-mur, ou une très grosse caisse
48*48 : dev_measurecrate03 : un muret assez haut. Le joueur peut sauter dessus en s'accroupissant
32*32 : dev_measurecrate02 : un petit muret. Le joueur peut sauter dessus sans s'accroupir
Une porte
dev_measuredoor01 représente une porte. Vous pouvez donc l'utiliser pour créer un bloc aux dimensions d'une porte standard. Vous devez aussi penser à découper le chambranle, comme indiqué avec les mesures précises sur la texture.
Un escalier
Voilà aussi un sujet assez déroutant pour les débutants : la taille des marches ! Qu'à cela ne tienne, il existe la texture dev_measurestairs01a qui vous aidera à vous représenter l'escalier et à découper le bloc sans problèmes.
Il existe d'autres textures comme la texture de rampe ou de rambarde ainsi qu'une texture d'échelle. Elles sont moins utiles, et je vous laisse les découvrir par vous-même.
Le wiki de Valve donne des informations concernant les dimensions dans Half-Life². Ces dimensions sont globalement les mêmes dans les différents mods. Je vous propose ici de voir quelques dimensions intéressantes, qui vous aideront à vous familiariser avec les grandeurs.
Système métrique
Hammer travaille en unités, et il est possible de savoir combien de mètres font une unité. Ce n'est pas super important, mais ça peut quand même vous être utile. Voici donc une table avec les données :
Unités
Mètres
Utilité remarquable
1
1 cm
2
4 cm
4
8 cm
Hauteur d'une bordure
8
15 cm
Hauteur de marche d'escalier
16
30 cm
32
60 cm
64
1 m 20
128
2 m 40
Mur d'un étage
256
4 m 90
Double mur
512
9 m 80
Les joueurs
Faire un conduit, un petit passage... c'est bien, mais encore faut-il savoir la taille des joueurs !
Obstacle au sol
Les joueurs peuvent franchir automatiquement (sans qu'il ne doive sauter) une hauteur de 18 unités, et ce que le joueur soit debout ou accroupi.
Passer sous
Debout, un joueur peut passer, sans s'abaisser sous une hauteur de 73 unités. Accroupi, il ne peut passer sous une hauteur de 37 unités.
Passer entre
Côté largeur, un joueur peut passer entre deux blocs éloignés de minimum 33 unités. Ainsi, un conduit d'aération doit au minimum faire 33 unités de large et 37 unités de haut.
Pente
A partir d'une inclinaison de 45 degrés, il n'est plus possible aux joueurs de grimper dessus.
Utiliser des objets
Un joueur prend automatiquement un objet si le centre de cet objet se trouve à 25 unités de lui ;
Un joueur peut "Utiliser" un objet, un bouton, une porte... à partir de 82 unités.
Le Source SDK n'embarque pas de documentation (il faut aller sur le Wiki de Valve pour ça) mais embarque en revanche toute une série de maps d'exemple, portant le préfixe sdk_. Ces maps d'exemple se trouvent dans le dossier sourcesdk_content\hl2\mapsrc (à partir de votre dossier de profil Steam).
Les maps techniques
Ce sont des maps qui expliquent (enfin, "expliquent" est un bien grand mot ^^ ) certaines techniques comme la manipulation des cubemaps, la création d'une grue avec un électro-aimant... c'est souvent assez complexe pour votre niveau actuel. Ces maps ne sont pas souvent belles (souvent texturées en orange), puisque leur but est d'expliquer, pas de passer un concours de beauté ^^ .
Les maps du jeu
Ici c'est déjà plus intéressant ! Il s'agit de maps tirées d'Half-Life² (et une de Half_life² Deathmatch). Ce sont donc des maps complètes que vous pouvez ouvrir avec Hammer pour regarder comment c'est fait. Je vous le dit tout de suite, ce sera compliqué de vous y retrouver au début ^^ . Voici la liste des maps que vous pouvez ouvrir, et je vous conseille de commencer par sdk_dm_lockdown qui est une map HL²DM, et donc un peu plus simple que les maps HL² (car pas de gestion des changements de niveau, de ciel en 3D...).
sdk_dm_lockdown.vmf ouverte dans Hammer
sdk_dm_lockdown.vmf : c'est la map HL²DM, et elle se trouve dans le dossier sourcesdk_content\hl2mp\mapsrc
sdk_background.vmf : elle est petite et plutôt vide, et est destinée à être chargée en arrière-plan du menu d'HL²
Il est temps de nous pencher sur différentes méthodes pour manipuler les blocs. On va en voir deux mauvaises, une bonne et une qui peut créer des problèmes, mais qui est d'une efficacité redoutable... eh oui, on n'a rien sans rien !
Le Clipping Tool est un outil de découpe. Il permet de couper des parties de bloc afin d'obtenir un bloc avec une forme plus complexe. C'est un outil extrêmement pratique. Nous allons donc voir comment nous en servir.
Commencez par créer un bloc. Une fois que c'est fait, sélectionnez votre bloc et prenez l'outil de clipping :
.
Maintenant, dans la vue 2D de coté (side) (ou une autre, comme vous voulez ^^ ), cliquez au milieu d'une arête, et maintenez le clic enfoncé. Déplacez votre souris vers l'arête perpendiculaire à la première. Une sorte de sélection blanche suit votre déplacement. Relâchez le clic une fois que vous êtes arrivé sur l'autre arête.
La zone « sélectionnée » en blanc sera la partie du bloc que vous allez conserver. Si vous préférez conserver l'autre partie, recliquez sur l'outil clipping pour inverser la sélection.
Quand tout est OK, faites Enter, sur votre clavier.
Votre bloc est maintenant clippé.
La troisième position
Je vous ai dit que si vous recliquiez sur l'outil de clipping, la sélection était inversée. Si vous recliquez une troisième fois dessus, tout se sélectionne et les 2 parties du bloc sont conservées, mais deviennent deux parties indépendantes :
Déplacement de la ligne de coupe
Avant de valider par Enter, vous pouvez modifier comme bon vous semble la position de la ligne de coupe. Il suffit pour cela de cliquer sur une des extrémités de la ligne et de la déplacer ;)
Un petit exercice
Il est important que vous vous familiarisiez avec l'outil clipping. Pour cela, je vais juste vous demander de reproduire la forme suivante (elle est évidemment faite de plusieurs blocs clippés (coupés) :
Moi, j'ai fait un bloc que j'ai coupé en 4 petits blocs. J'ai coupé ceux-ci par la suite. Vous pouviez très bien créer directement les 4 blocs et les couper après ;)
L'outil Carve, qu'on appelle souvent "carving" est à proscrire. Si j'en parle ici, c'est pour vous dire qu'il existe mais qu'il est mauvais de l'utiliser. L'outil Carve permet de trouer un bloc à l'aide d'un autre bloc. Voici les étapes :
Dans un premier temps, on a deux blocs : le bloc carvé est le gros vert, et le carvant est le bloc turquoise :
Ensuite, le but du jeu est de percer un trou dans le bloc carvé. Pour cela, on déplace le bloc carvant à l'intérieur du bloc carvé :
Dans une des vues 2D, on clic droit sur le bloc carvant et on clic sur Carve. Il ne reste plus qu'à retirer ou supprimer le bloc carvant. Si on sélectionne le bloc carvé on se rend compte qu'il a été découpé et que la partie qui était occupée par le bloc carvant n'existe plus :
Avec deux cubes, la structure obtenue n'est pas encore trop mauvaise. Mais si vous tentez l'expérience avec des cylindres, ça peut virer au cauchemars. Pour plus d'informations, voyez ce tutoriel d'optimisation, paragraphe Carve.
Le Hollow
Tout comme l'outil Carve, le Hollow n'est généralement pas conseillé. Il peut être utilisé pour aller plus vite, mais attention aux erreurs !
L'outil Hollow sert tout simplement à évider un bloc. Pour l'utiliser, sélectionnez un bloc (un gros bloc, qui fait tout le volume de votre pièce. Ensuite, cliquez droit sur le bloc dans une des vues 2D, et sélectionnez Make Hollow (ou Ctrl + H) :
Hammer vous demande l'épaisseur des murs ; Hammer va évider le bloc pour ne garder que 6 petits blocs qui feront office de murs, plafond et sol. C'est l'épaisseur de ces murs qu'il vous demande. 32 ou 16 sont de bonnes valeurs pour l'épaisseur d'un mur.
Vous pouvez spécifier une valeur négative. Dans ce cas, les 6 nouveaux blocs seront crées à l'extérieur du gros bloc (le volume déterminé par le gros bloc est alors le volume réel de la pièce). Voici 3 petits screens (en vue Top) pour illustrer ça :
Comme je l'ai dit, évitez le Hollow, et privilégiez la méthode suivante avec le Clipping Tool.
C'est ma technique préférée : créer un gros bloc - exactement comme pour l'outil Hollow - puis le découper comme je le veux avec le Clipping Tool. Pour ce fait, vous devez savoir utiliser le Clipping Tool de façon rapide, de manière à ce que cette méthode se révèle plus rapide que la création manuelle de 6 bloc séparés.
C'est un peu difficile de donner des screens pour illustrer, donc je vais juste vous expliquer la méthode de coupe que j'utilise.
passer le Clipping Tool en mode 3 (pour conserver les deux parties)
dans une des vues 2D de face ou de côté, couper horizontalement le bloc deux fois de suite (le sol et le plafond)
toujours dans une des vues 2D de face ou de côté, sélectionner le bloc du milieu, et couper deux fois pour obtenir deux murs
ensuite, passer en vue 2D Top, sélectionner le bloc du milieu et couper deux fois
pour terminer, supprimer le bloc du milieu qui ne sert plus à rien
Et théoriquement, vous devriez obtenir une belle pièce qu'il ne reste plus qu'à texturer :) .
Le Vertex Tool est un outil qui va nous permettre de créer des formes encore plus complexes qu'avec le Clipping Tool. Le Vertex Tool va nous permettre de déplacer les sommets et les arêtes d'un bloc.
Allez, on va commencer à jouer avec le Vertex Tool.
Créez un bloc et sélectionnez-le. Cliquez sur l'outil vertex :
Voyez, les sommets de votre bloc sont représentés par des carrés blancs et les milieux des arêtes par des carrés jaunes.
Dans une vue 2D, cliquez sur un sommet, et déplacez-le pour voir ce que ça donne :) Pour valider la modification, il suffit de cliquer sur l'outil de sélection.
En réalité, dans la vue 2D, vous ne déplacez pas qu'un sommet, mais plusieurs : vous déplacez tous les sommets qui sont dans l'alignement de celui sur lequel vous avez cliqué. Si vous ne souhaitez en déplacer qu'un, il vous suffit de le cliquer dans la vue 3D, et de le déplacer au moyen d'une des vues 2D.
Vous pouvez aussi déplacer un sommet sur un autre. Hammer va alors vous demander si vous voulez rassembler les 2 sommets en un seul :
Cette technique, je l'utilise souvent pour créer des triangles et autres formes moins courantes, comme les trapèzes par exemple.
D'ailleurs, pour vous exercer, vous allez créer un trapèze en 3D :) . C'est assez simple : à partir d'un bloc carré ou rectangulaire, il suffit de rapprocher les sommets du dessus vers le centre. Voici donc l'objet à reproduire (la vue 3D est en Wireframe) :
Quand vous manipulez des blocs avce le Vertex Tool, et dans une moindre mesure le Clipping Tool, certains "bugs" peuvent apparaître. Ces problèmes empêcheront Hammer de compiler votre map, ce qui peut être assez ennuyeux. Néamoins, ces bugs sont généralement simples à corriger, car Hammer vous les indiquera, notamment avec la commande Alt + P qui affiche les erreurs de la map.
Voyons donc les 3 erreurs qui peuvent apparaître quand on fait joujou avec les vertex !
Brush outside world
Traduction : un bloc est en dehors du monde.
C'est assez rare qu'un bloc se retrouve en dehors de la grille de Hammer, en revanche, il arrive parfois que les sommets d'un bloc ne soient pas alignés sur le grille de Hammer. On le vérifie en mettant la grille en grandeur 1. Ce genre de bug se produit quand vous opérez plusieurs modifications, notamment des redimensionnements sur des blocs complexes.
Voici un exemple :
Brush with coplanar faces
Traduction : un bloc possède des faces coplanaires.
Un bloc possède des faces qui se situent dans le même plan. Cela se produit généralement quand vous déplacez un sommet dans le même plan que deux autres. Par exemple, ce cube dans lequel je vais déplacer le sommet sélectionné (en rouge) ;
Le problème des faces non-planes est courant. Ce problème survient quand on déplace un sommet et qu'on le place dans un autre plan. Le face définie par ce sommet se retrouve alors dans une drôle de posture : elle n'est plus plate. Or, une face non plate, ce n'est pas acceptable ! Voici comment créer une telle surface...
En prenant un cube, il suffit de sélectionner un sommet dans la vue 3D, et de le déplacer via une des vues 2D, comme ceci :
>
On obtient alors une forme géométrique "hybride" qui ne ressemble à rien :
Quand on va compiler la map, le compilateur va se retrouver avec la face du dessus qui se trouve dans deux plans géométriques différents. J'ai coloré l'image pour bien montrer les deux plans de la face supérieure :
Ce problème de face non-plane est fréquent quand on déplace des sommets et il faut y faire attention. Ci-dessus, j'ai mis une texture de caisse, donc on voit clairement qu'il y a un problème. Mais, avec une texture de sol ou de mur, il peut être plus difficile de déceler le problème :
On ne constate pas que la face du dessus n'est pas valide. Si vous faites Alt + P, Hammer vous affichera l'erreur Invalid solid structure. Hammer peut corriger le problème si vous cliquez sur le bouton Fix, mais il y a 90% de chances que Hammer produise une structure inadaptée. Il vous faudra donc supprimer le bloc et le recréer, tout simplement.
Je vous proposerais bien de faire une maison, mais c'est un peu nul. Mon idée est donc de recréer une des salles de la prison de Nova Prospekt, dans Half-Life², car j'ai particulièrement apprécié ce chapitre. La salle que je vous propose de créer est assez simple, mais sera un bon entraînement.
Le sol
On va commencer par créer le sol. Mettez la grille de Hammer en taille 32, et créez un bloc de 512 unités de large, et 768 de long. Pour l'épaisseur, mettez ce que vous voulez, 64 par exemple. Sur la face supérieure, appliquez-lui la texture concrete/concretefloor013a :
Les murs du rez-de-chaussée
Après le sol, les murs. Un mur "normal" fait 128 unités de haut. Pour leur épaisseur, 24 unités conviendra, mais il vous faudra changer la taille de la grille : mettez-là à 8. Construisez les 4 murs de la salle, en faisant en sorte que leur arrête inférieure "côté sol" soit bien en contact avec ce sol. Appliquez la texture plaster/plasterwall034c sur les faces intérieures des murs :
Astuces
Une fois que vous avez créé un premier mur, dupliquez-le, avec la combinaison Majuscule + Flèche directionnelle, et déplacez-le ensuite à l'endroit voulu, avec la souris ou les flèches directionnelles. Ça vous évite de devoir redessiner un bloc, ce qui est une perte de temps.
N'oubliez pas qu'avec l'outil d'application de textures, vous pouvez sélectionner plusieurs faces en même temps, en maintenant le touche Ctrl enfoncée tout en cliquant sur les faces.
Les murs de l'étage
Une prison a des murs plus hauts qu'une maison, d'autant plus qu'il s'agit d'une grande salle dans laquelle nous ajouterons une passerelle. Sur nos 4 murs, nous allons monter 4 nouveaux murs, toujours de 128 unités de haut. Il faut savoir qu'en mapping, il es rare de faire de très grands blocs. On privilégiera généralement des blocs de petite taille pour pouvoir mieux jouer avec les textures. Les faces intérieures de ces 4 nouveaux murs seront texturées avec plaster/plasterwall034b, ce qui va permette de faire une continuité entre la texture du bas et la texture du haut :
Le plafond
Ici, c'est l'inverse du sol... On utilisera la texture plaster/plasterceiling008a pour la face visible du plafond. Tout comme le sol, une hauteur de 64 me semble bonne, bien qu'en réalité vous pouvez mettre ce que vous voulez :
Colonnes et poutres
En mapping, le plus gros souci est de trouver des idées pour "meubler" les salles. Ici, je vous propose d'ajouter 3 colonnes qui soutiennent une poutre. Le côté droit restera libre, car nous y ajouterons une passerelle par après. Les poutres et colonnes ressembleront donc à des L retournés :
Pour faire ça, il nous faudra 3 blocs : la poutre, la partie inférieure de la colonne et la partie supérieure (pour pouvoir mettre des textures différentes). Pour vous simplifier la vie, créez une première structure, que vous dupliquerez par après.
Les poutres et colonnes sont carrées, avec une largeur et une profondeur de 24 unités. Travaillez en taille de grille 8. Laissez une espace de 128 unités sur la droite, et texturez avez les mêmes textures que les murs. Pour la poutre, utilisez la texture plaster/plasterwall034a :
Pour finaliser la colonne/poutre, on va utiliser le Vertex Tool pour créer un angle à 45 degrés au niveau de l'intersection entre la poutre et la colonne. Cette technique vise simplement à réduire le nombre de faces invisibles (ce qui occasionnera moins de calculs pour l'affichage) :
Pour finir, sélectionnez vos 3 blocs, faites Ctrl + G pour les grouper. Dupliquez-les 2 fois pour obtenir 3 structures, et répartissez-les sur l'espace de votre salle : un au milieu (repérez-vous avec la petite croix au centre du bloc du "sol") et deux de part et d'autre. Vous devriez obtenir ceci :
On va maintenant mettre en place une passerelle assez simple. Commencez par tracer un bloc de 8 unités de haut, dont le dessus du bloc se trouve à la même hauteur que le dessus du mur du rez-de-chaussée, comme ceci :
Réduisez la taille de la grille, et prenez l'outil Clipping Tool. Avec ce dernier, on va couper la passerelle aux intersections avec les colonnes. Pour chaque colonne, coupez deux fois, à gauche et à droite :
Vue Top
Vous obtenez donc 3 gros blocs, et 3 autres plus petits, de la largeur des colonnes. Maintenant, agrandissez les 3 plus grands blocs pour les faire venir de part et d'autre des colonnes, comme ceci. Dès que c'est fait, placez une autre passerelle au fond de la pièce, et commencez à texturer les faces visibles, ce qui devrait vous donner plus ou moins ça :
Bon, on a une plate-forme en hauteur, mais il manque quelque chose pour y accéder. Nous aborderons les échelles par la suite, car elles ne sont pas toujours simples à mette en place et requièrent le maniement des entités, ce qui n'a pas encore été abordé. On va donc faire un escalier.
Une marche d'escalier fait généralement 8 unités de haut, sur 24 unités de profondeur. Quand à la largeur, c'est comme vous voulez, 128 pour un double, et 64 pour un simple escalier. Ici, les marches feront 128 unités de large pour coller avec la largeur de la passerelle.
Commencez par créer une première marche, celle du dessus. Comme je l'ai dit, 8 unités de haut, 24 de profondeur et 128 de largeur. Avec le Vertex Tool, transformez la marche en un triangle. Le côté incliné sera la "face" arrière de l'escalier :
Dès que c'est fait, texturez les faces avant et supérieure de la marche, avec la texture concrete/concretestair005a. Mais ici, il va falloir chipoter avec les réglages de la texture pour l'aligner correctement :
Activez le Texture Lock et dupliquez et la marche (avec Majuscule + Flèche directionnelle) et déplacez la copie. Répétez ça jusqu'à obtenir un escalier jusqu'au sol :
Désactivez le Texture Lock. Sélectionnez les faces arrières des marches, et appliquez leur une texture de plafond. Pensez à aligner les textures (mettez 0 à X et Y dans les cases Texture shift du panneau de propriété des textures.
Il ne nous reste plus qu'à placer un bloc pour fermer l'escalier du côté gauche. Faites un bloc de 4 unités de large que vous placez du côté gauche de l'escalier. Avec le Vertex Tool, modifiez le bloc pour qu'il épouse la forme de l'escalier :
Texturez le bloc avec la même texture que celle des marche, pour obtenir ceci :
En ce qui concerne les face gauches et droite du bloc, il vous faudra modifier l'angle (j'ai mis 35°) de la texture.
On va ajouter une balustrade pour ne pas tomber de la passerelle, ce serait gênant. Pour faire une balustrade, c'est très simple : créer un bloc et lui appliquer une texture de balustrade ! Il y en a plusieurs, que vous trouverez avec le mot clé rail. Moi, je vais utiliser metal/metalrail013c.
Créez un bloc de 32 unités de haut, sur 2 unités de large. Placez ce bloc entre l'escalier et la première colonne. Dès que c'est fait, appliquez la textures de rambarde sur les faces avant et arrière. Comme vous pouvez le constater, cette texture est spéciale : ce qui apparaît en noir est en réalité transparent !
Du côté de l'escalier, créez une montant, que vous allez texturer pour "fermer" la rambarde, comme ceci :
Vous avez compris le truc ? Bien, finissez la passerelle en ajoutant une rambarde entre chaque colonne :
Histoire d'encore un peu pratique, on va ajouter une petite pièce avec une porte et une fenêtre. C'est l'occasion de réutiliser le Clipping Tool pour faire des découpes au sein des blocs.
Dans le coin opposé à l'escalier, créez une pièce, faite de deux parois de 8 unités d'épaisseur. Pour faire plus joli, j'ai décidé de faire un coin oblique. Pour réaliser un coin oblique, créez un bloc normal et modifiez-le avec le Vertex Tool. Je texture avec plaster/plasterwall034d :
La porte
Dans la face avant, on va creuser un trou pour la porte. Prenez le Clipping Tool, mettez-le en mode 3 (pour conserver tout ce qui est coupé) et coupez deux fois dans le sans de la hauteur :
Dès que c'est fait redimensionnez le bloc central, qui sera le haut de la porte :
La fenêtre
C'est le même principe, sauf que le bloc du milieu sera coupé en deux horizontalement, pour obtenir le bas et le haut. Faites une fenêtre sur l'autre côté :
Les encadrements
Notre porte est un peu moche, de même que la fenêtre. Ce qu'il manque, c'est un encadrement. Créez-en un, avec une texture comme metal/metalwall062a. Faites ça proprement : pensez à raccorder les bords avec le Vertex Tool pour obtenir ceci :
Faites de même pour la porte.
Quand c'est fait, terminez la petite pièce en y plaçant un toit :
Les displacements servent à donner du relief à une ou plusieurs faces d'un bloc. On utilisera les displacements pour créer des collines, des trous d'obus, des paysages vallonnés, des falaises, des tas de gravats et autres éléments qui demandent du relief.
Pour vous illustrer la chose, voici 2 images de maps où l'on voit des displacements.
La première image est un screenshot tiré du solo d'Half-Life² (c'est juste avant d'arriver là où il y a la grue, où vous devrez soulever le buggy avec). Sur l'image, les rochers faisant office de falaises ainsi que le sol sont displacés ; on leur a appliqué des displacements. Je sais, l'image n'est pas belle, c'est en rapport avec ma FX5500 :D
La deuxième image est un screenshot de la map dm_avalon pour Half-Life²DM, réalisée par 3D-Mike, un ex-mappeur de chez Valve. Dans cette map, la quasi-totalité du décor est faite de displacements, ce qui donne un effet assez réaliste. Si vous ne connaissez pas cette map, voici sa page officielle : http://www.3d-mike.com/game/dm_avalon.htm.
Réaliser des displacements est en théorie très simple. Mais en pratique, ça l'est moins. Displacer un simple sol pour donner un peu de relief comme dans le premier screen est relativement simple. Par contre, les displacements de la map dm_avalon sont beaucoup plus compliqués à réaliser.
Créez un bloc, avec comme toujours la texture nodraw. Sur la face supérieure, appliquez une texture d'herbe (moi j'ai choisi nature/blenddirtgrass001a).
Bien. Reprenez l'outil d'application de texture et sélectionnez la face texturée. Dans la fenêtre de l'outil, il y a un onglet intitulé Displacement, cliquez dessus.
Pour le moment, nous ne savons encore rien faire. Cliquez sur Create pour créer un displacement. Une petite boîte de dialogue vous demande quelle est la « puissance » de displacement souhaitée. Vous avez le choix entre 2, 3 et 4. Laissez 3.
Comme par enchantement, toutes les faces non-sélectionnées de votre bloc disparaissent (dans la vue 3D). Seule la face sélectionnée subsiste ; elle est displacée. Votre face est « découpée » en triangles. Le principe du displacement est de modifier la position (verticale dans ce cas ci) des sommets des triangles, ce qui donnera un relief à notre face.
Création du relief
Vous êtes toujours sous l'onglet Displacement et votre face est toujours sélectionnée ? Bon, cliquez sur Paint Geometry. C'est cet outil qui va nous permettre d'élever et d'abaisser les sommets des triangles. Passez votre curseur sur votre face et vous verrez que votre curseur a encore changé de forme :)
La nouvelle fenêtre nous offre 2 options principales : Distance et Radius. Distance est tout simplement le nombre d'unités dont sera élevé ou abaissé un sommet. Radius est le diamètre de la grosse boule verte. Plus son diamètre est important, plus l'élévation ou la diminution sera large. Enfin, ce n'est pas facile à expliquer tellement c'est simple ^^ Faites 3 ou 4 tests en ayant modifié ces options :)
Pour élever ou abaisser un sommet, il suffit, dans la vue 3D de placer le curseur au-dessus du sommet et de cliquer soit droit, soit gauche.
Le cas des displacements verticaux
Vous pouvez bien entendu, comme dans le cas des falaises, displacer des faces verticales. La technique est un peu spéciale, car vous n'allez plus augmenter au diminuer la hauteur des sommets, mais bien avancer ou reculer les sommets. Pour cela, vous allez devoir modifier l'axe sur lequel vous travaillez (X, Y ou Z).
Pour spécifier l'axe sur lequel vous travaillez, c'est la liste déroulante Axis du panneau Paint Geometry. Par défaut, vous travaillez en Face Normal, ce qui équivaut en fait à l'axe des Z (Z-Axis). Les axes verticaux sont donc soit X soit Y, tout dépend de la position de votre face. Modifiez simplement l'axe de travail et testez pour voir lequel est le bon ;)
Vertical et horizontal
Continuons dans l'optique des falaises :) Si la falaise n'était constituée que d'une face verticale, ça ne rendrait pas bien. Donc, les faces verticales et horizontales sont displacées de manière à former une courbure plus jolie.
Pour réaliser ce genre d'effet, il suffit de sélectionner la face du dessus ainsi que la face verticale et de créer un displacement.
Ensuite, il n'y a plus qu'à travailler les faces :)
Pour plus de facilité, vous pouvez sélectionner les 2 faces en même temps et donc passer de l'une à l'autre sans aucun problème ;)
Ahhhh, le Paint Alpha, que voilà quelque chose de très pratique :)
Bon, comment vous expliquer ce que c’est… Voici plutôt 2 images : la première sans alpha et la deuxième avec.
Grace à l’alpha, on va en quelque sorte apposer une autre texture sur la première. Mais attention, on ne fait pas cela avec n’importe quelle texture. On fait cela avec toutes les textures qui contiennent blend dans leur nom. D’ailleurs, ces textures sont représentées avec les 2 types de couleurs dans l’explorateur de textures.
Ce fameux alpha permet de créer des sentiers (un peu comme dans la deuxième image), et de donner plus de réalisme aux décors et aux displacements.
Pour peindre l’alpha, il vous suffit de cliquer sur le bouton Paint Alpha de l’onglet Displacement. Le Paint Alpha s’utilise un peu de la même façon que le Paint Geometry.
Pour augmenter (ajouter) de l’alpha, cliquez avec le bouton gauche. Pour diminuer, cliquez avec le bouton droit.
Invert Alpha
C’est un outil qui permet tout simplement d’intervertir les 2 couches. Dans mon premier exemple, le sable deviendrait de l’herbe, et l’herbe du sable. Like this :
L'outil Noise et un petit outil qui permet de générer du relief. Pour cela, il suffit de rentrer la valeur minimale d'élévation ainsi que la valeur maximale, et le tour est joué :)
La valeur minimale peut être un nombre négatif, ou un nombre positif.
Sew, l'égaliseur de terrain
L'outil Sew vous permet d'égaliser 2 (ou plus) displacements ensemble. Mais pour cela, il faut certaines conditions. Les displacements doivent être du même Power, se toucher et leur zone commune ne peut être qu'égale, 2 fois plus grande ou 2 fois plus petite.
L'outil Subdivide est un outil très spécial, et c'est assez compliqué de vous expliquer concrètement à quoi il sert. Pour être simple, je vais vous dire qu'il sert à arrondir. Et pour vous le prouver, voici un exemple.
Faites un bloc, et créez-y des displacements sur la face supérieure et sur un côté. Sélectionnez ces 2 faces, et cliquez sur le bouton Subdivide puis admirez !
->
En fait l'arête toute droite séparant les 2 faces a été incurvée et donne un arrondi parfait.
Je vais maintenant vous montrer 3 petites astuces.
Le 1er exemple, mais en mieux
Le problème de l'exemple ci-dessus, c'est qu'il reste des « coins ». Pour qu'il n'y en ait pas, c'est très simple.
Créez 3 blocs identiques placés en ligne l'un à côté de l'autre
Sélectionnez toutes les faces supérieures ainsi que les faces de côté (que vous comptez displacer)
Créez un displacement
Subdividez
Supprimez les 2 blocs à l'extrémité, ne gardez que le bloc central
->->->
La sphère
Alors là, rien de plus simple :
Créez un bloc
Sélectionnez ce bloc avec l'outil de sélection
Créez un displacement. Toutes les faces du bloc seront alors displacées
Subdividez, et admirez votre sphère
Le cylindre
C'est un peu comme pour « le 1er exemple mais en mieux ». Nous allons ici créer un cylindre, pour faire une colonne par exemple.
Créez 3 blocs identiques les uns au-dessus des autres
Sélectionnez tous les blocs, et créez un displacement
Vous allez maintenant supprimer les displacements de TOUTES les faces supérieures et inférieures des cubes. Pour cela, sélectionnez la face, et dans l'onglet Displacement, cliquez sur Destroy
Sélectionnez les 3 blocs, et subdividez-les
Supprimez le bloc du dessus ainsi que celui du dessous. Il vous reste donc le bloc central qui fera office de colonne
Je vais laisser là main à Tydax, qui va vous expliquer un peu plus en détail comment faire de bons displacements. Je vous ai expliqué la base, il va vous expliquer comment ne pas foirer vos emplacements !
Je vais vous parler des décals et des overlays. Ce sont deux techniques/outils qui permettent d'appliquer une texture sur une autre. C'est très pratique pour décorer un peu vos murs et ajouter une touche de réalisme, par exemple :) .
L'outil décal est symbolisé par un bloc de couleur brique avec une cible dessus. C'est cet outil qui va nous permettre d'appliquer un décal.
Mais, c'est quoi un décal ?
Un décal est une texture généralement de petite taille, possédant des zones transparentes, que l'on appose sur une texture. C'est comme si vous colliez une décalcomanie sur votre peau. Ici, on colle une texture sur une autre.
Apposer un décal
Plaquer un décal est assez simple. Commencez par choisir une texture de décal (bah oui, logique ^^ ). Cliquez sur Browse pour choisir la texture. Les décals officiels peuvent être listés très facilement en tapant decal (ou decals) dans le champ Filter :
Parcourez les textures proposées histoire de voir un peu tout ce qui est proposé.
Humm, elles sont bizarres tes textures, tu trouves pas ?
C'est vrai, mais il faut que vous pensiez à une chose : quand le décal sera appliqué, son arrière-plan sera transparent.
On va faire un petit exemple pour que vous compreniez mieux. Tapez dans le champ Filter : decals/decal_posters006a, et double-cliquez sur la texture trouvée.
Maintenant, prenez l'outil décal. Le pointeur de votre souris change alors de forme et ressemble à une sorte d'étoile difforme ^^ . Il ne vous reste plus qu'à cliquer au centre du bloc sur lequel vous voulez apposer ce décal :
->
Et voilà, votre décal est appliqué :) . Et remarquez, l'arrière-plan est transparent ;) .
Déplacer et supprimer un décal
Bien évidemment vous pouvez supprimer ou déplacer votre décal. Pour ce faire, prenez l'outil de sélection, et zoomez au centre du décal dans la vue 3D. Au centre du décal se trouve une petite croix en 3 dimensions. Cliquez dessus pour sélectionner le décal. Ensuite, si vous voulez le supprimer, utilisez la touche Delete de votre clavier.
->
Pour le déplacer, utilisez les touches directionnelles dans les vues 2D. Mais attention, n'enfoncez pas le décal dans le mur, ou ne le faites pas sortir. Déplacez-le seulement de gauche à droite et de haut en bas (ou vice-versa ^^ ).
Les overlays ressemblent aux décals mais ceux-ci ont quelque chose en plus ! Avec les décals, vous appliquez une texture qui ne se répète pas. Grâce aux overlays vous pouvez faire répéter cette texture ce qui peut-être avantageux dans certains cas. Les overlays peuvent aussi êtres apposés sur les displacements, chose impossible avec les décals.
Apposer un overlay
Il n'y a rien de difficile : ça se fait exactement comme pour un décal, sauf que vous pouvez prendre la texture que vous voulez, ça ne doit pas nécessairement être une texture decal. Cela dit, vous pouvez rechercher les décals en mettant overlay dans Filter, mais la liste n'est pas bien grande. L'outil pour appliquer un overlay se trouve juste en dessous de l'outil décal.
Modifier un overlay
Une fois appliqué, l'overlay ressemble au décal : il mesure la même taille que sa texture. Mais, dans les vues 2D apparaissent des poignées de redimensionnement qui vous permettent de modifier la largeur et la hauteur de l'overlay. En fonction de ces modifications, la texture se répète :
J'ai déjà vaguement parlé des entités, mais je n'ai pas été très bavard. Voici pour moi l'occasion de me racheter :) .
On distingue tout d'abord 2 types d'entités :
Les entités-point
Les entités-bloc
Entités-point
Les entités-point, comme leur nom l'indique, sont un point de l'espace. Ce point de l'espace possède une fonction bien précise. Par exemple, l'entité appelée light est une « ampoule ». C'est de ce point là que démarrera une source lumineuse.
Les entités-point sont très nombreuses. On y trouve par exemple :
Le point de départ d'un joueur
Une arme posée par terre
Une source sonore (du son est diffusé à partir de cette entité)
Un personnage
Les models
...
Pour insérer une entité, c'est très simple : cliquez sur l'outil
. Allez maintenant dans la liste déroulante Objects du petit panneau Objects, et sélectionnez light dans ladite liste.
Il ne vous reste plus qu'à la créer, comme un bloc. Vous cliquez dans une des vues 2D et vous cliquez droit puis validez Create object.
Dans votre vue 3D, vous avez maintenant une jolie petite ampoule.
Entités-bloc
Les entités-bloc sont comme les entités-point, mais elles possèdent un volume. C'est un bloc qui est devenu une entité. Ce type d'entité sert par exemple à définir un espace, une zone dans laquelle il se passera quelque chose. C'est le cas des zones d'achat de CS. Toute la zone est un bloc dans lequel les joueurs peuvent acheter, s'ils s'y trouvent. Une porte peut être une entité-bloc. Elle aura alors des paramètres qui feront que si le joueur se trouve tout près, elle s'ouvrira.
Pour créer une entité-bloc, rien de plus simple : créez un bloc et sélectionnez-le. Dans le panneau vu précédemment, cliquez sur ToEntity. Pour supprimer le caractère d'entité d'un bloc, il suffit de cliquer sur ToWorld.
Une fenêtre s'ouvre alors, et la liste déroulante Class vous permet de définir l'entité créée. Je vous parlais des zones d'achat de CS. Dans ce cas, c'est func_buyzone.
Généralement, les entités-bloc dans lesquelles le joueur peut rentrer (entités-bloc invisibles) sont texturées avec la texture tools/toolstrigger.
Ce qui fait l'entité c'est avant tout ses paramètres. Sélectionnez une entité dans votre fenêtre 3D et faites Alt+Enter (ou clic droit > Proprieties dans une des vues 2D). Une fenêtre comme cela s'ouvre :
ou
Il y a 5 onglets principaux :
Class info
Outputs
Inputs
Flags
VisGroup
Class et Flags
Class
L'onglet Class Info est très important. C'est sous celui-ci que se trouvent les paramètres (ou les attributs) généraux de l'entité sélectionnée. Tous ces paramètres sont dans la zone Keyvalues.
Vous avez la possibilité de modifier tous ces attributs. Pour cela, cliquez sur l'un d'eux. La valeur de l'attribut est alors affichée dans la zone de droite, juste au dessus de la zone Help.
Par exemple, cliquez sur Brightness (qui veut dire Luminosité en français). La valeur de cet attribut est alors affichée dans le champ de saisie à droite, et un bouton appelé Pick Color (Choisir la Couleur) est apparu. Vous pouvez cliquer dessus, et vous pourrez alors choisir la couleur qu'aura votre lumière ;) . Il en va plus ou moins de la même façon pour tous les autres attributs.
Le petit radar ainsi que la zone de saisie Angles permettent de définir l'orientation de l'entité. Cette fonction n'est pas active dans le cas d'une entité de classe light. Par contre, vous pouvez passer la classe (champ Class) en light_spot, et dans ce cas, vous aurez la possibilité de définir l'orientation.
Bien sûr, nous reviendrons sur les paramètres de chaque entité dans les parties suivantes. Ici, c'est juste pour vous montrer comment ça fonctionne.
Flags
Passez sous l'onglet Flags. Sous cet onglet sont présent d'autres paramètres, mais ce sont seulement des paramètres booléens (coché ou non). Dans le cas de notre light, il n'y a qu'un paramètre : Initialy Dark. Si ce flag est coché, la lampe sera éteinte, jusqu'à ce qu'on l'allume (ce que nous verrons plus tard).
Les outputs et les inputs servent en quelque sorte à faire communiquer plusieurs entités entre elles. C’est ce qui va nous servir à créer des boutons qui allument une lampe, qui provoquent un bombardement, et plein d’autres choses marrantes ^^ .
Au début, ça me paraissait très obscur, je ne pigeais pas bien comment les utiliser. Je ne comprenais pas ce que venaient faire les inputs, et c’est pour cela que je ne vous parlerai pas beaucoup ce ces inputs (du moins au début), car seul les outputs suffisent pour vous expliquer comment ça marche.
Un output est une sorte de commande qui va servir à appeler une autre entité. Par exemple, si un joueur passe dans une certaine zone, il y a un tremblement de terre. Dans ce cas, quand le joueur sera dans la zone, l’entité-bloc (la zone donc) va appeler l’entité qui se chargera de créer un tremblement de terre. C’est ce qu’on appelle l’output.
Je vais vous montrer de quoi se compose un output.
Allez sous l’onglet Outputs.
La grande zone blanche montre tous les outputs créés. Vous n’en avez aucun, bien évidemment. Pour créer un nouvel output, il faut cliquer sur Add.
Les champs de saisie auparavant grisés vont s’activer. Il va falloir les remplir.
My output named : c’est le nom de l’output. C’est en fait un événement qui déclenchera l’output. Suivant l’entité sur laquelle vous créez un output, la liste que Hammer vous propose est différente. Si vous connaissez, c’est quelque chose de semblable aux événements Javascript (onclick, onmouseover…)).
Targets entities named : c’est le nom de l’entité qui sera appelée par l’output. Le nom d’une entité se définit dans son paramètre Name.
Via this input : c’est ce qui se passera au niveau de l’entité qui sera appelée. Par exemple, une lumière (light) peut soit s’allumer soit s’éteindre.
With a parameter override of : c'est un paramètre additionnel. On laissera généralement ce champ vide (sur <none>). Nous l'utiliserons lors de la création d'outputs plus complexes.
After a delay in seconds of : c’est le temps avant que l’output ne soit déclenché. Si le champ vaut 0 (0.00), alors l’output est déclenché instantanément.
Ca, c’est de la théorie. Vous comprendrez mieux comment utiliser ces fameux outputs dans les mini-tutos suivants.
Voici un exemple d’output :
OnStartTouch, (dès que l'entité-bloc est touchée), elle appelle l’entité dont le nom est boumfaitlabombe, et lui dit qu’elle doit exploser (Explode) après 3 secondes.
Par la suite, dès que nous allons rencontrer une nouvelle entité, je vous donnerai, dans un tableau, son nom, son type et un résumé de son utilité. Le nom sera un lien vers le Wiki officiel de Valve, où vous pourrez trouver des informations plus complètes sur l’entité en question. Ces informations seront en anglais, mais ont comme principale utilité de lister tous les outputs et tous les inputs de l’entité, car je ne le ferai pas à chaque fois (bien trop long ou inutile).
info_player_start est le point de départ d'un joueur dans une map pour Half-Life² (une map solo).
Dans la vue 3D, cette entité est représentée par Gordon Freman lui-même, tout modélisé en vert, excepté ses lunettes et sa barbichette ^^ .
Cette figuration représente la taille réelle d'un personnage dans le jeu, vous pouvez l'utiliser comme repère pour créer vos maps.
Cette entité ne possède pas d'attribut spécifique, si ce n'est son orientation, mais ça, vous pouvez le définir directement via les vues 2D, comme un simple bloc.
Dans les maps multijoueurs, il y a plusieurs points de réapparition (de respawn). On utilise l'entité info_player_deathmatch.
Il est important de toujours placer un info_player_start, même dans les maps multijoueurs. En effet, cette entité symbolisera le point de départ de la caméra en mode Spectateur.
Et dans le cas des maps Team Deathmatch ?
J'y viens ;)
Rebels VS Combines
En fait, dans une map Deathmatch normal, tout le monde respawn (réapparaît) dans n'importe quel info_player_deathmatch. Vous savez qu'on peut jouer en mode Team (Rebels contre Combines). Dans la plupart des maps, ce sont des info_player_deathmatch qui sont utilisés : combines comme rebels utilisent les même points de respawn, comme dans les maps dm_resistance, dm_avalon, enfin, quasi toutes).
Mais le cas de dm_runoff est spécifique. Dans le camp rebel, il n'y a que des info_player_rebel, et dans le camp combine, que des info_player_combine. Ainsi, chaque team respawn dans son camp respectif.
Et si ce n'est pas du Team Deathmatch ?
Ben alors, tous les points de respawn sont utilisés pour faire réapparaître les joueurs. Vous pouvez également placer des info_player_deathmatch. Ceux-ci ne seront utilisés que si le serveur est en mode Deathmatch simple (pas du Team).
Point de respawn d'un soldat de la Wehrmacht dans DOD:S
Counter Strike Source
Les deux entités sont info_player_counterterrorist et info_player_terrorist. Je pense que les 2 types d'entités peuvent se passer de commentaires, c'est assez logique il me semble ;) .
Day Of Defeat Source
De même que pour Counter-Strike, les 2 entités n'on pas besoin d'êtres expliquées. info_player_allies, c'est pour l'armée US, et les info_player_axis, pour la Wehrmacht.
Pour placer un model dans votre map, rien de plus simple, il suffit de placer une entité prop_static.
L’apparence du model va se définir dans les propriétés de l’entité, et plus particulièrement dans la propriété World Model. Cliquez dessus, puis cliquez sur Browser pour ouvrir l’explorateur de models.
Dans la fenêtre d’explorateur, vous avez une liste dans laquelle les models sont classés. Cliquez sur un des items de cette liste. Le contenu de cette catégorie s’affiche alors dans la zone juste en dessous. Vous y voyez le nom du mod pour lequel chaque model est disponible ainsi que le nom du model. Si vous cliquez dessus, vous pouvez voir le model en 3D dans le cadre de droite.
Pour l’exercice, nous allons insérer le model de l’APC des combines (leur 4x4). Pour cela, saisissez apc dans Filter. Dès que le model est trouvé, cliquez sur OK. Validez ensuite vos propriétés et ajustez le placement du model au moyen des vues 2D :
Propriétés usuelles
Skin : certains models peuvent avoir plusieurs skins, c'est-à-dire plusieurs apparences. Par exemple, suivant le skin choisi pour un arbre, celui-ci peut soit être nu, soit être touffu, ou entre les deux, comme en automne. Pour savoir si votre model possède des skins, avec l’explorateur de models, sélectionnez votre model, et cliquez sur l’onglet Skins. Le skin par défaut s’appelle skin0. Pour spécifier un skin, il vous suffit d’indiquer le numéro du skin de votre model dans la propriété Skin du prop_static.
Collisions : cette propriété peut prendre 3 valeurs :
Not Solid : le model est alors traversable par le joueur, il ne butte pas contre. C’est très utile pour de petits models comme des cannettes, des seaux, des débris… En effet, c’est râlant de devoir sauter au dessus d’une cannette pour ne pas butter contre ^^ .
Solid :c’est le contraire de Not Solid
Use Bounding Box : c’est une combinaison de Not Solid et Solid. Certaines parties du model sont traversables, d’autres non. Pour savoir quelles parties seront solides, dans l’explorateur de models, il suffit de cocher la case Collision Model. Des lignes rouges apparaîtront sur le model, dans la vue 3D de l'explorateur, pour indiquer le squelette imperméable du model.
Permet d'insérer un model physique dans une map multijoueurs
On entend par model physique, un model qui réagit aux lois de la physique. Ce sont les objets comme les caisses, les blocs, et autres petites choses pouvant être utilisées avec le Gravity Gun.
La mise en place d'un prop_physics se déroule comme un prop_static. Il y a juste quelques propriétés qui diffèrent.
Damage filter : Nom de l'entité filter_damage_type qui définira le type de dommages occasionnés si le model est brisé.
Explosion damage : Dégâts causés par l'explosion.
Explosion radius : Grandeur du rayon du cercle dans lequel agit l'explosion.
Performance mode : Type de débris générés une fois le model cassé
Normal : il y en a un peu.
No Gibs : il n'y en a pas.
Full Gibs on All Platforms : il y en a beaucoup.
Preasure delay : Temps en secondes avant que le model ne se casse à cause d'une pression exercée (quelque chose fait pression sur le model, un joueur par exemple).
Mass Scale : permet de multiplier la masse de l'object. Ca permet de le rendre plus lourd.
Les prop_physics sont utilisés dans les maps solo. Généralement, dans une map multijoueurs, on préférera utiliser des prop_physics_multiplayer. Ce sont exactement les deux mêmes entités excepté que le prop_physics_multiplayer demande moins de ressources, ce qui est plutôt bénéfique en multijoueurs.
Permet d'insérer un model physique cassable qui réapparaîtra
Quand vous cassez une caisse ou une table dans une partie d'HL²DM, elle réapparaît après un certain temps.
Tout se paramètre de la même façon qu'un prop_physics. Pour modifier le laps de temps entre chaque réapparition, modifiez simplement la propriété Respawn Time. Le temps est par défaut de 60 secondes.
Pour alléger les calculs du moteur d'affichage, il est possible de masquer un model à partir d'une certaine distance. C'est extrêmement pratique et ça permet vraiment de soulager le moteur.
La distance de visibilité se paramètre avec les deux propriétés Start Fade Dist/Pixels et End Fade Dist/Pixels.
Start Fade Dist/Pixels : c'est la distance à partir de laquelle le model commence à disparaître.
End Fade Dist/Pixels : c'est la distance à partir de laquelle le mode a complètement disparu.
Ce n'est pas facile de juger la distance comme ça, au pif. Vous voyez, il y a une icône de caméra (
). Cliquez dessus, et Hammer va calculer la distance entre le model et la caméra 3D.
Mais ce n'est pas suffisant ! Il y a moyen de régler le Fade autrement. Cliquez sur le bouton Toggle Helpers (
). Maintenant, dans les vues 2D (votre model est toujours sélectionné), sont présents deux cercles. Ce sont en fait les deux cercles qui délimitent la distance de visibilité (le Start Fade et le End Fade). Vous pouvez les agrandir ou les rétrécir avec les poignées de redimensionnement.
Comme je vous l'ai déjà dit je ne sais plus où, light représente une source lumineuse. Ce n'est donc pas une lampe "en dur" que le joueur peut voir ! Il ne verra que la lumière. C'est pourquoi il faut généralement placer l'objet qui générera la source lumineuse, sinon le joueur va croire que la lumière sort du néant, ce qui n'est pas très réaliste ^^ .
Voici comment placer une entité light :
Comme vous pouvez le voir, la light n'est pas collée au model de tube néon (le model est models/props_wasteland/prison_flourescentlight002b.mdl), et ce pour une bonne raison : light envoie de la lumière dans toutes les directions, et si elle était trop proche du néon, et donc des murs, il y aurait un jeu de lumière particulièrement affreux qui se reflèterait contre ces derniers. Il convient donc de toujours distancer une light des murs.
Alors, elle va servir à quoi light ?
A créer de l'ambiance, à ajouter de la lumière où il n'y en a pas assez par exemple. Enfin, ce n'est pas facile à expliquer, alors regardez :
Tout au fond, il y a une lampe qui éclairera le coin et la moitié de la pièce. Le toit est percé d'une espèce de coupole laissant entrer le soleil. J'ai placé une light en plein milieu de la pièce. C'est cette light qui va ajouter un peu de luminosité. Evidemment, ça ne doit pas être une light comme un spot de 1000 Watts ^^ . C'est une légère lumière qui ajoute un petit plus à l'ambiance lumineuse de la pièce.
Voici quelques propriétés :
Brightness : c'est la couleur de la lumière. Très important comme propriété. Les 3 premiers nombres sont les codes de couleur RVB. Vous les définissez en cliquant sur Pick Color. Le quatrième nombre est important et on l'oublie souvent : c'est l'intensité de la lumière. Plus le nombre est élevé, plus la lumière est lumineuse. 150 ou 200 sont de bonnes valeurs. On peut même descendre plus bas de manière à créer de plus beaux jeux d'ambiance.
Appearance : vous permet de donner un effet spécial à votre lumière. Aidez-vous de la liste ci-dessous pour choisir l'effet qui vous plaît :
Normal : c'est l'apparence que l'on utilise la plupart du temps. La lumière reste allumée.
Fluorescent Flicker : utilisé pour obtenir une lumière cassée, généralement un néon. Celle-ci clignote aléatoirement.
Slow, strong pulse : la lumière s'éteint et se rallume progressivement.
Slow pulse, noblack : c'est pareil, mais la lumière ne s'éteint pas aussi longtemps.
Gentle pulse : la lumière clignote mais reste allumée.
Flicker A : clignote assez rapidement.
Flicker B : la lumière s'éteint brusquement, et se rallume progressivement.
Candle A : cet effet est utile lorsque la lumière provient d'une bougie. Elle s'éteint et se rallume de temps en temps, comme si le vent agissait sur la bougie.
Candle B : idem, mais dans un autre style.
Candle C : idem, c'est un autre effet, histoire de varier...
Fast strob : effet stroboscope garanti. La lumière clignote très rapidement. J'espère que vous n'êtes pas épileptiques !
Slow strob : pareil, mais ça clignote moins rapidement. Heureusement pour nos yeux ! Ce style permet de mettre une réelle ambiance dans votre map car la lumière ne s'allume que par intermittence.
Il n'y a qu'un seul et unique flag pour light : Initialy Dark. Cochez-le si vous souhaitez que la lampe ne soit pas allumée par défaut. Dans ce cas, il faudra prévoir un bouton pour l'allumer. Nous y reviendrons ;) .
Comme je vous l'ai laissé entendre dans la sous-partie ci-dessus, nous allons utiliser les light_spot pour générer une source lumineuse qui, au contraire de light, aura une direction. Pour résumer, c'est un spot ^^ .
Ici, le spot peut être placé sans problème près du model de néon. Le trait rouge symbolise la direction de la lumière.
Pour orienter un light_spot, faites-le tourner dans les vues 2D, tout simplement.
Les propriétés sont les mêmes que pour light, excepté quelques unes :
Inner : c'est la grandeur de l'angle à la sortie du spot, en degrés.
Outer : c'est la grandeur de l'angle que fait la lumière après la sortie du spot.
Il faut voir la lumière générée par light_spot comme un cône. Le sommet du cône est l'origine de light_spot. L'élargissement de cet angle est Inner. La base du cône, c'est Outer.
point_spotlight va nous servir à ajouter un effet supplémentaire à nos spots. C'est une entité qui permet de créer un faisceau lumineux. On n'utilise pas ça avec chaque light_spot ! Généralement, on utilise un point_spotlight avec un light_spot qui a pour vocation d'éclairer fort et loin, comme les phares des combines :
Un point_spotlight se place exactement comme un light_spot. Il convient de le placer juste à côté du light_spot et de l'orienter de la même façon.
N'oubliez pas de configurer ces 3 propriétés :
Color : la couleur du faisceau.
Spotlight Lenght : c'est la longueur du faisceau. Une valeur de 150 peut convenir.
Spotlight Width : la largeur du faisceau. Ici, une largeur de 50 est conseillée.
Ah oui, une dernière chose. Vous devez cocher les 2 flags, et en particulier le premier ;) .
Très important dans une map : l'ensoleillement. Celui-ci se définit avec l'entité-point light_environment.
Cette entité possède 3 propriétés très importantes : Pitch Yaw Roll, Brightness et Ambiant. Vous connaissez les 2 premières, mais pas la troisième. Ambiant est tout simplement la couleur des ombres qui seront générées par l'ensoleillement.
Comme ce n'est pas facile, il existe des listings des paramètres à attribuer à un light_environment en fonction du sky.
env_sun est la représentation visuelle du soleil. Ce n'est pas obligatoire de la placer, mais ça peut être un plus, notamment pour les maps qui se déroulent à l'aube ou au couché du soleil.
Avec un env_sun
Sans env_sun
(Les screens viennent de la map factice de la tortue facile. J'avais la flemme d'en recréer une moi-même ^^ ).
Cette entité prend les mêmes paramètres que le light_environment ;) .
Après les lampes, pourquoi ne pas voir les câbles ? Ben oui, ce sont eux qui vont servir à acheminer l'électricité, et ainsi donner plus de réalisme.
Faire des câbles est quelque chose de relativement simple. Un câble est caractérisé par une entité de départ, (le move_rope) et des points d'attache (des keyframe_rope).
Donc, un simple câble aura un début (move_rope) et une fin, qui sera son seul point d'attache, en plus que le move_rope.
Allez, placez dans votre map le move_rope. Remplissez sa propriété Next Keyframe en mettant cable_1. Ensuite, créez un keyframe_rope, que vous nommerez cable_1.
La propriété Next Keyframe indique le point d'attache suivant du câble. Vous pouvez mettre autant de keyframe_rope que vous le voulez. Il vous suffit de tous les nommer et de remplir correctement leur propriété Next Keyframe.
Comme propriétés, nous avons ceci :
Slack : c'est la tension (la courbure) du câble. N'ayez pas peur de mettre une valeur importante comme 100 voir 150.
Type : c'est le type de câble. On laisse généralement Rope. Si on met sur Rigid, les effets du Slack sont annulés (ben oui, le câble est rigide et non courbé ^^ ).
Subdivision : c'est le nombre de câbles. Vous pouvez mettre une valeur allant de 1 à 8. Si vous mettez 5, il y aura 5 câbles qui partiront du point A pour arriver au point B. Plus il y a de câbles, plus le moteur graphique doit calculer. C'est pourquoi il n'est pas bon de mettre plus de 3 câbles ;) .
Width : comme vous l'aurez deviné, c'est la grosseur du câble. Une valeur de 1 ou de 2 est raisonnable. Les valeurs décimales sont aussi acceptées, comme 0.5 ;) .
Collide with world : si vous voulez que le câble se cogne contre les autres éléments.
Start dangling : si le câble semble séparé de son point d'accroche (pas super utile comme truc).
env_spark vous permet de créer des étincelles. C'est assez pratique pour mettre de l'ambiance, comme dans une salle à moitié inondée et pleine d'appareils électriques.
Pour mettre des étincelles, placez un env_spark où vous souhaitez en avoir. Ensuite, paramétrez l'entité :
Max Delay : le temps maximum entre deux étincelles.
Magnitude : c'est l'intensité des étincelles. Vous avez le choix entre Petite, Moyenne et Grande (en anglais ^^ ).
Spark Trail Length : c'est le longueur de la traînée des étincelles.
Il y a aussi quelques flags :
Start On : très important ça.
Glow : mettre un effet de lueur.
Silent : pas de bruit.
Directional : pour orienter les étincelles suivant un angle (le Pitch Yaw Roll).
Comme nous sommes dans l'électricité, je vais vous parler des lasers. Mettre quelques rayons lasers peut ajouter un peu d'ambiance dans votre map.
Pour mettre en place un laser, il nous faut trois entités : deux info_target et un env_beam. Les info_target sont des entités qui n'ont pas d'utilité précise, si ce n'est de représenter un point. Les paramètres du laser se définiront avec l'env_beam.
Bon, placez un premier info_target où vous désirez que votre laser commence. Vous nommerez cette entité laser_1a. Ensuite, vous placez le deuxième info_target où vous voulez que votre laser finisse. Appelez cette dernière laser_1b.
Voilà, les points de départ et d'arrivée de votre laser sont placés. Il ne reste plus qu'à les « attacher » entre eux. C'est ce que nous allons faire avec l'env_beam.
Placez votre env_beam où vous voulez, ça n'a pas d'importance. Ouvrez ses propriétés, et dans Start Entity, mettez laser_1a. Dans End Entity, mettez laser_1b. Voilà, votre laser est presque fini :) .
Voici mon exemple (j'ai placé des models pour faire les « générateurs » du laser, pour ne pas qu'il sorte du mur comme par magie ^^ ) :
Il reste d'autres propriétés. Et certaines sont importantes :
Beam color : c'est la couleur du laser. Moi, comme mes points de départ et d'arrivée sont rouges, je mets mon laser en rouge.
Life : ça c'est la durée pendant laquelle votre laser va rester activé avant de s'éteindre puis de se rallumer. Moi je mets 0, pour que le laser soit permanent.
Width of Beam : c'est l'épaisseur du laser.
Amount of noise : plus la valeur que vous allez entrer ici est grande, plus votre laser va s'agiter, un peu comme un éclair.
Damage / Second : les points de vie qui seront retirés par seconde si le joueur passe dans ce laser.
N'oubliez pas de cocher le flag Start On, sinon votre laser ne sera pas déclenché par défaut. Il y a d'autres flags intéressants comme Start/EndSparks qui définissent si vous voulez des étincelles au début/à la fin de votre laser.
Permet de faire bouger un point par rapport à un autre.
Une lampe qui se balance, ça vous dit ?
Eh ben je vais vous expliquer comment en faire une :) .
Pourquoi tu n'as pas expliqué ça dans le mini-tuto sur les lampes ?
Parce qu'on n'avait pas encore étudié les câbles :D .
Cette petite partie va donc faire intervenir un peu tout ce qu'on a déjà vu, comme les câbles, les models physiques et les lampes.
Pour commencer, au plafond, créez une entité move_rope. Paramétrez-la comme suit :
Citation : Entité
Next KayFrame : fil_1 Width : 1 Position Interpolator : Linear
Maintenant, placez une entité keyframe_rope, à la hauteur où vous désirez que votre lampe soit, avec ces propriétés :
Citation : Entité
Name : fil_1 Parent : lampe_1 Width : 1
Donc, souvenez-vous, ceci est le câble (le fil) de la lampe.
Maintenant, créez un prop_physics. Ce sera notre lampe. Vous devez la placer juste sous le keyframe_rope. Paramétrez-le comme suit :
Citation : Entité
Name : lampe_1 World Model : models/props_c17/lamp_standard_off01.mdl
Remarquez, la propriété Parent du keyframe_rope contient le nom du prop_physics. Cela veut dire que ce keyframe_rope, ou plutôt le bout du fil est parenté (« attaché ») au prop_physics. Ca aura pour effet de faire balancer le bout du fil en même temps que la lampe si le joueur tire dessus.
Voici ce que vous devriez avoir :
Bon, continuons. Placez un phys_ballsocket sur le move_rope. phys_ballsocket que vous paramétrez comme ceci :
Citation : Entité
Entity 1 : lampe_1
Cette entité bizarre marque l'origine du système de balancement. La première entité liée à cette dernière est le prop_physics (lampe_1). En réalité, et pour faire bref, le phys_ballsocket va s'occuper de gérer le balancement.
Nous avons presque fini. Il ne reste plus qu'à placer la lumière. Placez un point_spotlight juste sous la lampe :
Mais, c'est bizarre ça, le light_spot n'est pas parenté à la lampe ?
Non. C'est tout à fait possible de le faire, mais alors il faut utiliser un light_dynamic en lieu et place du light_spot. Mais le light_dynamic a un très gros problème : il demande beaucoup de ressources et de calculs et en particulier pour les petites configurations.
Vous pourrez tester dans le jeu, on ne remarque pas trop que la source lumineuse est fixe, car le point_spotlight donne l'impression que la lumière suit vraiment la lampe.
Nous allons maintenant voir comment déclencher des actions. Nous allons, pour cela, un peu voir comment se servir des outputs. Si vous n'aviez pas bien compris ce que c'était, vous allez comprendre :) .
Déclenche un output, une seule fois, au passage du joueur
Dans ce premier exemple, le joueur passera dans une zone, et la lumière s'allumera. La zone dans laquelle le joueur passera sera ce que l'on appelle, en mapping, un trigger. Trigger veut dire déclencheur en anglais.
Un trigger_once est une zone de déclenchement. Elle a comme particularité de ne pouvoir appeler qu'une seule fois une ou plusieurs entités.
Dans mon exemple, j'ai placé le trigger_once entre les 2 grilles, et le light_spot se trouve au dessus des barils explosifs. Le light_spot a son flag Initialy Dark coché. La lumière sera donc éteinte au démarrage de la map.
La première fois que le joueur passera dans le trigger_once, le spot s'allumera. Si le joueur repasse par après, il ne se passera rien.
Donnez un nom à votre light_spot. Je l'ai appelé super_lampe (la propriété Name). Maintenant, nous allons créer votre premier output :) .
Allez dans l'onglet Outputs, des paramètres du trigger_once. Cliquez sur Add, et rentrez ces valeurs :
Output named
Targets entities
Via this input
Parameter
Delay
OnStartTouch
super_lampe
TurnOn
<none>
0.00
Ca veut dire : quand le joueur touchera le trigger_once (OnStartTouch), il appellera l'entité nommée super_lampe en lui disant de s'allumer (TurnOn).
Ah oui, en parlant de flags, les triggers ont ceux-ci :
Clients : si coché, le joueur peut déclencher le trigger. Il est coché par défaut.
NPCs : si coché, tous les NPC peuvent le déclencher. Les NPC sont les monstres, les combines, enfin, tout ce qui « vit ».
Pushables : si coché, un objet peut être poussé dans le trigger pour le déclencher.
Physics Objects : un objet physique peut déclencher le trigger (par exemple, tirer un radiateur avec le Gravity Gun dans le trigger le déclenchera).
Only players ally NPCs : tous les joueurs et les NPC alliés (les gentils comme les vortigaults par exemple) déclencheront le trigger.
Only clients in vehicles : seulement le joueur s'il est dans un véhicule, comme le buggy de Freeman.
Only clients not in vehicles : seulement le joueur s'il n'est pas dans un véhicule.
Everythings : tout peut le déclencher.
Physics debris : les débris physiques peuvent le déclencher. Par exemple, s'il y a une caisse et que vous la cassez, les débris de cette caisse peuvent déclencher le trigger.
Le trigger_multiple s'utilise comme un trigger_once. La seule différence est que le trigger_multiple peut être déclenché plusieurs fois.
Mais attention, dans ce cas, nous n'allons plus utiliser TurnOn pour le Via this input. En effet, si la lumière vient d'être allumée et que le joueur repasse dans le trigger, la lumière ne s'éteindra pas (normal, puisqu'on va demander à super_lampe de s'allumer).
Mais alors, comment faire ?
Il suffit de mettre Toggle à la place de TurnOn. Ca veut dire qui si la lumière était allumée, elle s'éteint, et si elle était éteinte, elle s'allume.
Le trigger_multiple possède une propriété utile : Delay before reset. C'est le temps, en secondes, avant que l'on puisse réutiliser le trigger_multiple. Par exemple, si on met "4", et qu'on traverse le trigger une première fois, il ne se passera rien pendant 4 secondes si on retraverse la zone.
Vous vous attendiez à voir encore un trigger_machin ? Eh ben non, ici, c'est d'un logic_auto dont on va parler. Mais on ne va pas en parler beaucoup.
Logic_auto est une entité qui se déclenche au chargement de la map. Grâce à celle-ci, nous allons pouvoir appeler, toujours via des outputs, des entités lors du chargement de la map.
Je n'ai pas d?exemple à vous montrer (il n'y en a aucun qui me vient à l'esprit en fait) sur l'utilisation de ceci. Ah si, je peux vous dire que ça sert à initialiser certaines entités comme les monstres (les NPC), qui par défaut ne sont pas actifs dans une map.
Compte le nombre de fois que quelque chose est exécuté
Est-ce possible de déclencher quelque chose après par exemple 2 passages dans une zone ?
Ben, oui, c'est possible. Pour cela, nous allons utiliser un trigger_multiple et un math_counter. Cette dernière entité permettra de compter le nombre de passages.
Commencez par faire votre trigger_multiple. Ensuite, créez un math_counter et réglez-lui ses propriétés comme ceci :
Citation : math_counter
Name : compteur Initial Value : 0 Minimim Legal Value : 0 Maximum Legal Value : 2
Je pense que les 4 propriétés se passent de commentaire. Comme vous le voyez, le math_counter peut déclencher à 2 moments : quand une valeur minimale est atteinte, et quand une valeur maximale est atteinte. Dans mon cas, je n'ai besoin que d'une des deux, j'ai choisi de passer par la valeur maximale.
Maintenant, un petit output :
Output named
Targets entities
Via this input
Parameter
Delay
OnHitMax
super_lampe
Toggle
<none>
0.00
Voilà. Donc, quand le math_counter arrivera à sa valeur maximale (OnHitMax), il appellera super_lampe en lui disant de s'allumer (Toggle). Si vous aviez choisi de passer par la valeur minimale, vous auriez utilisé OnHitMin comme output.
Comme output de votre trigger_multipe, mettez :
Output named
Targets entities
Via this input
Parameter
Delay
OnTrigger
compteur
Add
1
0.00
Donc, quand on touche le trigger (OnTrigger (j'aurais pu mettre OnStartTouch, mais si je mets OnTrigger, il faut que le joueur soit bien dedans pour déclencher, c'est mieux)), il appellera compteur en lui disant d'ajouter (Add) 1 à sa valeur.
Mais après, le compteur est inutilisable ? Si je repasse encore 2 fois dans le trigger_multiple, ça ne fera plus rien ?
Effectivement. En fait, il faut remettre la valeur initiale du compteur à 0, après 5 passages. Pour cela, le math_counter va s'auto-appeler (on va lui faire un output à lui-même).
Prenez votre math_counter, et créez cet output :
Output named
Targets entities
Via this input
Parameter
Delay
OnHitMax
compteur
SetValue
0
0.00
Ce qui veut dire : "Quand il arrivera à sa valeur maximale, il appellera compteur (c'est à dire lui-même) en lui disant de redéfinir sa valeur initiale (SetValue) en la mettant à zéro (With a parameter override of)".
Voilà, je pense qu'avec ce premier mini-tuto portant sur les déclencheurs et les outputs vous avez compris ce que c’est. Vous avez aussi compris ce que sont les inputs. Ce sont donc les méthodes qui permettent d'agir sur l'entité cible (allumer la lampe, compter…).
Maintenant que nous avons vu les déclencheurs via des triggers (et un logic_auto), nous allons voir les déclencheurs que le joueur peut utiliser, comme les boutons et les vannes...
C'est le bouton le plus basique. Pour en faire un, créez votre bouton, avec soit des blocs, soit avec un model. Moi j'ai choisi de le faire avec un model (models/props_lab/freightelevatorbutton.mdl).
Si vous avez créé votre bouton avec un ou plusieurs blocs, sélectionnez-le(s) et convertissez-le(s) en func_button. Ce sera le bouton :) .
Pour le model, c'est différent. Créez un bloc avec la texture toolsinvisible, à l'endroit où se trouve le bouton. C'est ce bloc que vous allez convertir en func_button. Cochez son flag Don't move.
L'output de ce bouton est d'une simplicité, que je me demande même si je dois vous le donner ^^ . Vous allez le faire, ça vous fera un peu d'exercice.
Quand on appuie sur le bouton, celui-ci doit appeler la lampe et lui disant de s'allumer si elle était éteinte, ou de s'éteindre si elle était allumée.
Output named
Targets entities
Via this input
Parameter
Delay
OnPressed
super_lampe
Toggle
<none>
0.00
Voilà, vous venez de créer un fabuleux bouton :) .
model qui peut être parenté, être masqué, bouger, s'animer... (on reparlera plus en profondeur de cette entité sur la partie Téléportation)
Pour faire une valve (une vanne), vous avez deux possibilités : soit vous créez une vanne en bloc que vous transformerez en func_door_rotating, soit vous mettez un model de vanne que vous parentez à un func_door_rotating avec la texture invisible.
Mais door ça ne veut pas dire porte ?
Je vais partir sur le deuxième choix car je n'ai pas envie de créer une valve en blocs ;) .
Voilà, dans l'image suivante, j'ai créé un func_door_rotating, avec la texture toolsinvisible. Cette entité est un cylindre et est un peu plus grande que le model de la valve (models/props_pipes/valvewheel001.mdl). Je précise que la valve est un prop_dynamic, puisqu'elle tournera en même temps que l'entité func_.
Voici maintenant les propriétés utiles du func_door_rotating :
Speed : vitesse de rotation
Delay Before Reset : temps avant que la roue ne revienne à sa position initiale après avoir été tournée. Mettez -1 si vous ne voulez pas que la vanne revienne à sa position d'origine
Distance : le nombre de degrés qu'il faudra tourner avant que la vanne ne soit complètement ouverte
Quelques flags :
X/Y Axis : c'est l'axe de rotation
Passable : pour ne pas que le joueur se bloque dedans ^^
Toggle : si la vanne est fermée, on l'ouvre, et inversement
Use Opens : il faut appuyer sur la touche Utiliser pour tourner
Permet d'établir un relais d'appel entre plusieurs entités
Quand on a beaucoup d'outputs, il peut être intéressant de tous les centraliser au même endroit (la même entité). Pour cela, on va utiliser une entité neutre, appelée logic_relay.
C'est une entité qui n'a pas de fonction spécifique. Elle sert juste à établir une relation entre une entité et une autre.
Regardez ce schéma : un trigger appelle le logic_relay, qui à son tour va appeler une entité env_spark (l'entité pour faire des étincelles, souvenez-vous ^^ ) :
C'est nul ça, ont sait faire communiquer le trigger et l'env_spark sans logic_relay, non ?
Oui, on sait, et dans le cas de ce schéma, il vaut mieux :D . Maintenant, imaginez, vous avez plusieurs triggers dans votre map. Tous ces triggers appellent 3 entités (une env_spark, une light et une autre non-définie (obsolete)). Cela veut donc dire que vous devez, pour tous vos triggers, créer les outputs vers chaque entité appelée. C'est contraignant ! Dans ce cas-ci, un logic_relay peut s'avérer pratique :
Vous voyez, c'est le logic_relay qui va se charger d'appeler les entités ciblées. Ainsi, vous n'aurez qu'à faire UN simple output vers le logic_relay, pour chaque trigger :) .
Pour appeler un logic_relay, utilisez sont input Trigger, comme ceci :
Output named
Targets entities
Via this input
Parameter
Delay
OnStartTouch
gentil_relay
Trigger
<none>
0.00
Pour appeler une entité à partir du logic_relay, utilisez l'output OnTrigger :
Permet de filtrer en fonction de l'équipe d'appartenance d'un joueur
Dans les propriétés des entités de type trigger, vous en avez peut-être repéré une qui s'appelle Filter Name.
Filter Name fait référence à un type d'entités bien spécifique les : filter_activator_ .
Il y a 3 entités de bases présentes dans cette classe d'entités (suivant le mod pour lequel vous mappez, d'autres entités de ce type peuvent être présentes, comme filter_activator_tfteam si vous mappez pour Team Fortress²) :
filter_activator_class
filter_activator_name
filter_activator_team
Ces entités permettent de créer des filtres pour autoriser, par exemple, l'équipe blue à déclencher un trigger.
C'est un peu difficile à comprendre, je vais prendre un exemple concret.
J'ai un trigger_multiple qui ne doit être déclenché que par un joueur de l'équipe rouge. Pour ce faire, je lie le trigger à un filter_activator_team. Je configure cette dernière pour qu'elle retourne vrai si c'est un joueur de l'équipe rouge qui se trouve dans le trigger. Si c'est un joueur bleu, le filtre retournera faux, et le trigger ne sera pas déclenché.
C'est pratique non ?
Propriétés :
Name : le nom de l'entité
Filter mode : mode de filtrage
Allow entities that match criteria : valeur par défaut, comme dans mon exemple ci-dessus
Disallow entities that match criteria : c'est le contraire. Pour reprendre mon exemple, si c'est un bleu qui se trouve dans la zone, le trigger sera déclanché.
Filter * : c'est le paramètre de filtrage. Le nom de cette propriété diffère suivant l'entité.
Filter_activator_class
Cette entité filtre en fonction du nom de classe. Par exemple, si vous faites une map solo pour Half-Life², vous pouvez n'autoriser que certaines entités (classe = nom d'entité). Les citoyens sont des entités npc_citizen. Si vous mettez npc_citizen dans la propriété Filter Classname, il n'y aura que les citoyens qui valideront le filtre (il renverra "vrai").
Filter_activator_name
C'est le même principe que filter_activator_class, sauf que vous filtrez les entités en fonction de leur propriété Name (qui est différent du nom de l'entité !).
Filter_activator_team
Ça c'est comme dans mon exemple, cette entité sert à filtrer en fonction de l'équipe. Suivant les mods, le contenu de la propriété Filter Team peut différer (soit 0 ou 1, soit red soit blue).
Permet d'alléger le calcul pour les blocs ne faisant pas partie intégrante de la structure de la map.
Pour illustrer l'utilisation des func_physbox, j'ai décidé de les mettre en scène dans un escalier.
Un func_physbox est un bloc, qui réagit aux lois de la physique. Il peut tomber, être attrapé avec le Gravity Gun... C'est un peu l'équivalent du prop_physics, mais pour un bloc.
Mais, quel rapport avec un escalier ?
En fait, je vais créer un escalier dont les marches centrales tomberont quand vous marcherez dessus.
Commencez par créer un escalier. Dans mon exemple, je vais prendre un escalier simple, composé de deux montants et de marches.
Mettez vos marches et vos montants en func_detail. Laissez juste quelques marches, au centre de l'escalier, en blocs.
Voici le moment d'apprendre les func_details :) . Ces derniers, inexistants sous Half-Life 1 sont indispensables sous le moteur Source. Retenez bien ceci : tout ce qui n'est pas un bloc de structure doit être en func_detail. J'entends par bloc de structure des blocs importants comme les murs, les plafonds, le sol. C'est l'architecture basique de la map. Tout le reste doit être en func_detail, comme les poutres, les colonnes, les rebords... donc tout ce qui est un détail et qui ressort d'un mur.
Et pourquoi ?
C'est pour une meilleure optimisation de votre map. Plus votre map est optimisée, moins votre carte graphique souffrira. Les func_details servent à soulager le moteur d'affichage.
Bon, de retour à notre escalier :) . Convertissez en func_physbox, une à une, les marches que vous avez laissées en bloc.
Dès que c'est fait, sélectionnez les toutes, et faites Alt + ENTER pour éditer leurs propriétés.
Name : donnez un nom, par exemple escalier_sadique.
Material Type : mettez Metal. C'est pour indiquer que ces marches réagiront comme du métal (ça fera donc un bruit de métal en tombant)
Ben en fait c'est tout ^^ . Ah non, cochez le flag Start Asleep. Grâce à ce flag, les func_physbox vont rester en l'air et non tomber au chargement de la map.
Les autres propriétés ne sont pas utiles et je pense que vous pouvez déjà les comprendre à peu près toutes tout seul :) .
Maintenant, il va falloir déclencher la chute des marches quand je joueur passera dessus. Pour ça, rien de plus simple : un trigger_once.
Celui-ci comprendra cet output :
Output named
Targets entities
Via this input
Parameter
Delay
OnTrigger
escalier_sadique
EnableMotion
<none>
0.00
EnableMotion veut dire qu'on va autoriser les func_physbox à bouger. C'est comme si le flag Start Asleep se décochait, ce qui fait que les marches tomberont :) .
Permet de créer des points de sorties pour une échelle
Sous le moteur Source, pour faire une échelle, il faut un début et une fin :) .
Comme je le disais, il faut deux points pour définir une échelle. Ces deux points vont être créés avec une entité func_useableladder. Malgré la particule func_ dans le nom de l'entité, c'est une entité-point !
Alors, pour faire une échelle, commencez par la créer en blocs ou avec un model (recherchez ladder dans l'explorateur de models). Dès que c'est fait, créez l'entité func_useableladder à la base de l'échelle. Ce sera le début de votre échelle.
Au centre de cette entité, dans les vues 2D, il y a un petit cercle. Cliquez dessus et maintenez le clic enfoncé en déplaçant le bloc vers le haut. Cette deuxième partie de l'entité sera la fin de votre l'échelle. Essayez de positionner cette deuxième partie dans l'axe de la première partie (sauf si vous avez fait une échelle oblique ^^ ).
Pour finir la structure de votre échelle, donnez lui un nom. Ca nous permttra d'utiliser les dismounts...
Les dismounts
Les dismounts sont des points de sorties de l'échelle. Ce sont des endroits ou le joueur peut poser les pieds de façon à sortir de l'échelle en toute sécurité. Il faut placer des dismounts au début et à la fin de l'échelle (bah oui, si le joueur descend au lieu de monter ^^ ).
L'entité pour placer un dismount est info_ladder_dismount. Placez-les comme ceci :
Maintenant, vous n'avez plus qu'à renseigner la propriété Laddername avec le nom de votre échelle, de façon à lier les dismounts à l'échelle ;) .
Sous Counter-Strike Source, pour faire une échelle, c'est tout simple (même trop simple ^^ ). Il suffit de créer un bloc en lui appliquant la texture toolsinvisibleladder. Le bloc se place devant l'échelle, où le joueur passera, comme ceci :
Ici, pas de dismounts ni rien. Juste un bloc texturé :) . CS c'est le mapping pour les feignants :D .
Pour faire un bloc qu'on peut afficher et masquer de façon toggle
L?entité func_brush est une nouvelle entité apparue avec le moteur Source. Elle a pour fonction de remplacer les entités func_illusionary, func_wall et func_wall_toggle, ces dernières datant de HL1, mais toujours présents sous Source.
Le func_brush possède tout un tas de propriétés, mais je ne vais vous en citer que deux, qui je pense, sont les principales :) .
Start Disabled :
Yes : le bloc ne sera pas visible par défaut
No : le bloc sera visible par défaut
Solidity : spécifie la solidité du bloc
Never Solid : le bloc ne sera jamais solide
Always Solid : le bloc sera toujours solide, et ce, même si il est masqué (via le Start Disabled)
Toggle : si le bloc est affiché, il est solide. S?il est masqué, il n?est pas solide. C?est la position sur laquelle je place généralement cette propriété.
Grâce à cette entité, vous pourrez, par exemple, créer un champ de force (un bête bloc avec une texture de champ de force comme effects/com_shield003a) entre deux plates-formes qui sera affiché si le joueur appuie sur un bouton.
Pour afficher ou masquer le func_brush via les outputs, vous devrez utiliser les inputs Disable et Enable. Dans le cas de mon champ de force, mon output serait (Start Disabled est renseigné avec Yes) :
Output named
Targets entities
Via this input
Parameter
Delay
OnPressed
champ_de_force
Enable
<none>
0.00
Tu parles du func_illusionary, ça servait à quoi ce truc sous HL1 ?
C?était tout simplement un bloc non-solide. Il est donc remplacé par la propriété Solidity du func_brush.
Et les func_wall et func_wall_toggle ?
Le func_wall est l?ancêtre du func_detail. Quant au func_wall_toggle, c?est un bloc que l?on peut masquer et afficher, comme le func_brush. Cela dit, le func_wall_toggle a la possibilité d?être commandé via l?input Toggle, que le func_brush ne possède par (il n?a que Disable et Enable). Rappelez-vous le tuto sur les lampes, avec l?input Toggle. Ici, c?est pareil : si le mur était masqué, il s?affiche et vice-versa. Ca peut être utile dans certains cas, mais c?est plutôt rare ;) .
Quoi de plus amusant dans une map que de pouvoir tout casser ? Rien me direz-vous, et vous avez raison ^^ . C?est pour cela que je vais vous montrer comment faire un bloc cassable.
L?entité est func_breakable (breakable veut dire cassable en anglais). Voici les propriétés utiles de cette entité de barbare :
Explosion Damage : c?est la puissance de l?explosion si l?entité est cassée. Si vous laissez 0, il n?y aura pas d?explosion
Explosion Radius : c?est le rayon dans lequel l?explosion se fera ressentir
Performance Mode : c?est utilisé pour définir le nombre de débris que génèrera le cassage
Normal : la quantité de debris est normale
No Gibs : il n?y a aucuns debris. Le calcul pour le moteur d?affichage est donc plus simple
Full Gibs on All Platforms : il y a beaucoup de débris, et donc beaucoup de calculs d?affichage
Strength : c?est le nombre de points de vie que possède l?entité. Plus le nombre est élevé, plus le bloc est résistant. Si vous mettez 0, l?entité ne sera pas cassable avec des armes (il faudra la casser avec les outputs par exemple)
Material Type : très important, c?est le type de matériau dont est faite l?entité. Si vous avez fait une caisse en bois, choisissez Wood
Spawn On break : c?est ce qui apparaîtra une fois le bloc cassé
Explode Magnitude : c?est l?intensité de l?explosion
Et voici les flags disponibles :
Only Break On Trigger : pour seulement casser via un trigger (output)
Break On Touch : pour casser dès qu?on le touche
Break On Pressure : pour casser si une pression est exercée sur l?entité (si vous marchez dessus par exemple)
Break immediately on Physics : pour casser le bloc dès qu?il est pris
Don?t take physics damage : pour ne pas qu?il provoque de dommages s?il heurte le joueur
Faire une vitre est quelque chose de très simple. En effet, il vous suffit de mettre une texture de vitre (glass, pour le filtre de l?explorateur de textures) sur la face visible. Toutes les autres faces doivent impérativement être recouvertes de nodraw, y compris la face inverse de celle texturée (l?autre côté quoi ^^ ) ! C?est tout :) .
C?est vraiment tout ?
Non. Votre vitre ne sera pas cassable. Pour la rendre cassable, convertissez-la en func_breakable, et n?oubliez pas de mettre la propriété Material Type en position Glass ;) .
Mais si vous cassez cette vitre, elle va se casser d?un coup, comme du temps d'Half-Life1. Pour donner une effet réaliste (la vitre se casse par morceaux), nous allons utiliser un func_breakable_surf.
J'ai pris le screen juste au moment ou un rebel me lançait une grenade. La déflagration fait péter les vitres, ça donne un bel effet ^^ .
Les propriétés ce cette dernière sont les même que pour un func_breakable. Strenght a juste changé de nom est et devenu Health. Il y a deux propriétés qui sont apparues :
Fragility : c?est la fragilité de la vitre une fois qu?elle est cassée. Si vous tirez dans la vitre, elle va se morceler. C?est la fragilité des ces morcellements que définit cette propriété
Surface Type : c?est le type de surface. Laissez Glass.
Il reste une chose pour améliorer notre vitre (cassable ou pas) : la réflexion. C?est ce que je vais vous expliquer maintenant :) .
L?env_cubemap est une entité assez abstraite. Pour faire simple, elle sert à créer des reflets.
Vous devez placer cette entité au centre de toutes vos pièces. Une fois votre map compilée et lancée, vous devez tapez buildcubemap dans la console.
Le jeu va alors créer toute une série d?images, qui sont les reflets de l?environnement. Ces images sont appelées des cubemaps. Les images sont prises de l?endroit où se trouve l?env_cubemap.
Les cubemaps ne sont pas visibles partout. En effet, seule certaines textures sont réfléchissantes (quelques textures de métal, les textures d?eau et de vitres).
Si vous faites une vitre, vous devez placer un env_cubemap (en plus de celui qui est déjà dans la pièce) près de celle-ci, et faire pointer cet env_cubemap vers la vitre.
Pour cela, nous allons nous servir de sa propriété Brush faces. Cliquez sur Pick et, dans la vue 3D, allez cliquer sur la vitre (la face qui est face à l?env_cubemap). Vous pouvez aussi picker (faire pointer l'env_cubemap vers une ou plusieurs faces) plusieurs faces en maintenant la touche Ctrl enfoncée.
Dans un premier temps, nous allons voir comment créer une porte translative.
Translaquoi ?
C'est une porte qui coulisse :) . La porte coulissante est la plus simple à réaliser. Bon, commençons la création !
Créez le bloc qui fera office de porte et transformez-le en func_door. C'est tout. Il ne reste plus qu'à paramétrer l'entité.
Speed : c'est la vitesse de déplacement de la porte. Une valeur de 100 est tout à fait correcte.
Start Sound : son qui sera joué à l'ouverture de la porte.
Stop Sound : son qui sera joué à la fermeture de la porte.
Delay Before Reset : temps avant que la porte ne revienne à sa position initiale. Si vous mettez -1, la porte ne reviendra pas, elle restera ouverte.
Lip : c'est le nombre d'unités dont la porte dépassera une fois ouverte. Par défaut, le déplacement de la porte est égal à sa largeur (ou profondeur/hauteur suivant l'orientation). Si la porte fait 100 unités de largeur, elle se déplacera de 100 unités. Maintenant, si vous mettez un lip de 10, elle se déplacera de 90 unités.
Health : c'est la vie de la porte. Laissez 0 si vous ne voulez pas qu?on ouvre la porte en tirant dessus. Si vous le souhaitez, spécifiez la vie de la porte.
Locked Sound : son joué si la porte est verrouillée et que le jouer tente de l'ouvrir.
Loop Moving Sound : Mettez Yes si vous voulez que le Start Sound soir joué en boucle jusqu'à ce que la porte ait fini de s'ouvrir.
Move Direction : très important, c'est la direction d'ouverture de la porte. Vous devez vous référer à la vue du dessus (Top) pour orienter le radar. Vous pouvez aussi choisir Up ou Down si vous voulez que la porte monte ou descende.
Voilà pour les principales propriétés. Voici maintenant les flags.
Starts open : la porte sera ouverte par défaut
Non-solid to Player : la porte ne sera pas solide pour le joueur (sans intérêt)
Passable : on peut passer au travers (sans intérêt)
Toggle : assez pratique. La porte reste chaque fois dans sa dernière position jusqu'à ce qu'on l'actionne
Use Opens : il faut appuyer sur Utiliser pour ouvrir la porte
NPCs Can't : le NPC (joueurs et monstres contrôlés par l'ordinateur) ne peuvent pas se servir de la porte
Touch Opens : toucher la porte pour l'ouvrir
Starts locked : la porte sera verrouillée par défaut
Voyons maintenant comment créer une porte traditionnelle, avec des blocs. Nous verrons par après comment faire une porte avec un model (cette porte là aura une clenche).
La porte rotative fonctionne exactement comme la porte translative. Il va juste falloir spécifier l?axe de rotation et l?angle d?ouverture.
Allez, convertissez votre bloc de porte en func_door_rotating. Ensuite, activez l?option Toggle Helpers (
). Vous devriez voir apparaître une grosse boule mauve au centre de votre porte :
Cette boule est le centre de l?axe de rotation vertical de la porte.
Dans la vue 2D du dessus, déplacez la boule (elle est au centre du bloc et votre curseur se transforme en croix) et mettez-là sur un coté de la porte :
Ainsi, votre porte s?ouvrira comme une porte normale (si vous aviez laissé le boule au centre, la porte aurait tourné sur elle-même).
Toutes les propriétés sont les mêmes que pour une func_door sauf la propriété Move Direction qui est remplacée par la propriété Distance. C?est tout simplement l?angle d?ouverture de la porte, en degrés. 90 est une valeur appréciable, puisque c?est l?angle droit.
Voici juste quelques flags en plus :
Reverse Dir : la porte s'ouvrira en sens inverse
One-way : on ne peut ouvrir la porte que dans un sens
X axis : par défaut, la porte s'ouvre selon l'axe des Z (vue Top). Mais vous pouvez la faire tourner selon l'axe des X si ça vous chante (c'est très rare quand même)
Permet de créer un bloc rotatif qui peut revenir en place
Ici, il s'agit de créer une porte de garage qui s'ouvre en même temps que le joueur tourne une vanne. A la fin d'Half-Life² EpisodeOne, Gordon ouvre une porte de cette manière pour faire passer Alyx. Il se fait alors canarder par un strider.
Nous avons vu comment réaliser une vanne, dans le chapitre sur les déclencheurs (La VALVe). Nous allons donc en créer une de la même façons (un model parenté à un momentary_rot_button avec une texture invisible).
Ehh, tu nous avais appris à faire une vanne avec un func_door_rotating. Pourquoi on prend cette nouvelle entité ?
momentary_rot_button se comporte de la même façon que func_door_rotation, mais il possède quelque chose en plus : il revient à sa position initiale quand on le lâche (quand on lâche la vanne donc).
Vous appellerez ce momentary_rot_button, door_vanne. Ensuite, il faut créer la porte de garage. Faites votre bloc, et transformez-le en func_movelinear. Vous l'appellerez door_garage. La configuration est simple, si ce n'est quelques paramètres :
Move Direction : c'est la direction dans laquelle le bloc bougera. Ici, la porte va monter, donc sélectionnez Up dans la petite liste déroulante.
Start Position : c'est le position de départ. Si votre porte est fermée, mettez 0.
Move Distance : c'est la distance, en unités de Hammer, sur laquelle l'entité va pouvoir bouger. Ca correspond généralement à la hauteur de votre bloc (moins quelques unités).
Revenons à notre momentary_rot_button. Il y a quelques propriétés à modifier :
Speed : vitesse de rotation en degrés par secondes
Distance : c'est le nombre de degrés maximum dont l'entité tournera
Auto-return Speed : c'est la vitesse de rotation quand la vanne est lâchée et qu'elle revient à sa position initiale
Start position : position de départ. Mettez 0.
Start Direction : direction dans laquelle tournera la vanne. Laissez Forward (en avant).
Vous pouvez aussi cocher certains flags comme Not Solid, Use Activate et l'axe de rotation (moi c'est Y Axis).
Passons maintenant aux outputs appliqués sur door_vanne :) .
Output named
Targets entities
Via this input
Parameter
Delay
OnFullyClosed
door_vanne
Lock
<none>
0.00
Position
door_garage
SetPosition
<none>
0.00
Le premier output dit que quand la vanne est complètement fermée, elle s'appele elle même pour se bloquer. Ainsi, elle ne retournera pas à sa position d'origine si elle est complètement fermée.
Pourquoi c'est pas OnFullyOpen ?
C'est tordu ça ^^ . L'état initial est Open, et l'état final est Close. Donc quand la vanne est tournée, elle est fermée (close).
Le deuxième output appelle la porte door_garage à chaque fois que le position de la vanne change (quand vous tournez quoi ^^ ). Et à chaque fois on va modifier, avec SetPosition, la position de la porte sur son axe, en fonction de l'ouverture de la vanne. Donc, plus on tourne, plus la porte s'ouvre :) .
Sous Source, créer de l'eau est très simple. En effet, tout comme les vitres, il suffit de faire un bloc recouvert de nodraw et d'appliquer une texture d'eau sur sa face supérieure.
Pensez aussi à mettre un env_cubemap et à picker la face texturée de votre bloc d'eau. L'env_cubemap est nécessaire pour les cartes graphiques ne supportant pas DirectX9, et donc ne disposant pas du calcul des reflets en temps réel. Les reflets seront donc calculés à l'avance via cet env_cubemap ;) . Avec ma FX5500, je bénis ce système :D .
Si vous mettez de l'eau, vous devez placer une entité water_lod_control qui va vous permettre de configurer la qualité du rendu de l'eau. Cette entité est souvent ignorée des mappeurs, et des maps de trois blocs avec un piscine fait parfois plus ramer la carte graphique que le chapitre en bordure d'eau du solo d'Half-Life² (chez moi en tous cas).
Cette entité possède deux propriétés :
Start Transition to Cheap Water : c'est le nombre d'unités à partir duquel le rendu de l'eau deviendra moins beau. Une valeur de 500 est conseillée.
End Transition to Cheap Water : c'est le nombre d'unités à partir duquel le rendu de l'eau sera définitivement moins beau. Une valeur de 1000 voir 800 est indiquée.
Donc, plus vous vous éloignerez moins beau sera le rendu de l'eau et les calculs effectués par votre carte graphique seront moindres. Cela se remarque fort avec les petites cartes graphique, genre FX5500. Pour les cartes graphiques plus puissantes, la transition belle/moche eau est quasiment imperceptible, puisque ces cartes sont capables de toujours afficher un bon rendu.
De l'eau qui ne bouge pas, c'est nul ! Imaginez, le joueur est dans une salle. Tout à coup, l'eau monte. C'est déjà plus amusant :) .
Pour faire bouger de l'eau, il suffit de convertir le bloc d'eau en func_water_analog et de le paramétrer. Il suffira de l'appeler via un de ses inputs.
Vous devez penser à mettre le func_water_analog dans sa position d'origine. Je veux dire par là que vous devez le déplacer (l'enfoncer dans le sol), et nom le raccourcir. Voici maintenant comment le paramétrer :
Move Direction : très important, c'est le sens dans lequel bougera votre eau
Speed : c'est la vitesse de déplacement
Move Distance : distance, en unités, dont le bloc sera déplacé
Sound played when the water brush starts moving : son joué dès que le mouvement commence
Sound played when the water brush stops moving : son joué dès que le mouvement s?arrête
Wave Height : hauteur des vagues, en unités
Pour déplacer l'entité, vous devez l'appeler avec son input Open. Pour la faire revenir à son emplacement d'origine, il faut utiliser l'input Close.
Comme on parle de l'eau, pourquoi ne pas parler de l'hydroglisseur ?
L'airboat (nom anglais de l'hydroglisseur) se place avec l'entité prop_vehicle_airboat. Cette entité se paramètre de la même façon qu'un prop_. Il y a juste une ou deux options différentes.
Start locked : mettez Yes si vous voulez que l'airboat ne soit pas utilisable par défaut. Il vous faudra alors l'activer via l'input Unlock (ou Lock si vous voulez le rendre non-utilisable)
Has Gun : mettez Yes si vous voulez que l'hydroglisseur soit équipé du gauss (le canon à impulsion)
Ajouter des sons dans sa map est quelque chose d'assez important. Ca permet de créer une bonne ambiance, et de rajouter tous ces petits plus qui font que la map est agréable :)
La pose d?un son se fait avec l?entité-point ambient_generic. C?est très simple, et rapide. Voici les paramètres utiles disponibles :
Propriétés
Name : nom de l?entité
Sound Name : nom du son joué. Utilisez le browser de sons pour trouver le son idéal. N?oubliez pas d?utiliser le filtre de recherche, c?est très pratique
Volume : volume du son. Le maximum est 10.
Dynamic Presets : Préréglages. Vous avez plusieurs options disponibles, pour ajouter de l'effet à votre son
Start Volume : volume de départ
Max Audible Distance : distance maximum dans laquelle le son sera entendu par le joueur.
Flags
Play everywhere : le son sera joué partout. La propriété Max Audible Distance est alors inutile
Start Silent : le son ne sera pas joué par défaut, il faudra le déclencher
Is NOT Looped : le son ne sera pas joué en boucle
Vous vous souvenez comment voir dans les vues 2D et 3D la visibilité d'un model ? (le bouton
de la barre d'outils). Eh bien, avec ce bouton, vous pouvez aussi voir la portée du son (la Max Audible Distance).
model qui peut être parenté, être masqué, bouger, s'animer... (on en a déjà parlé, mais ici il revient en force)
Réaliser un téléporteur simple est quelque chose de très facile. La zone de téléportation se défini avec l?entité-bloc trigger_teleport. Voici les 2 propriétés utiles disponibles pour cette entité :
Start Disabled : mettez No si vous ne voulez pas que le téléporteur soit désactivé par défaut
Remote Destination : le nom de l?entité qui fait office de destination
Pour créer la destination, on utilise l?entité info_teleport_destination. Cette entité n?a pas de propriétés spécifiques, excepté qu?elle peut être parentée.
Et tu fais tout un mini-tuto pour me dire ça ?
Attendez ! Nous allons faire un téléporteur DeLuxe? , avec un model animé et tout. Un peu de patience ^^ .
Nous allons utiliser un model de téléporteur. Allez le chercher, c?est models/props_combine/combine_teleportplatform.mdl. Insérez-le au moyen d?un prop_dynamic.
Ne changez pas les propriétés, celles par défaut sont bonnes. Spécifiez simplement un nom, via la propriété Name. Mettez model_tele_combine.
Comment va-t'on s'y prendre pour activer le téléporteur quand le joueur est dedans ?
Avec un trigger_multiple, tout simplement. Je vous ai dit que le trigger_teleport comprenait la propriété Start Disabled. Nous allons la mettre sur Yes. Une fois le joueur dans le trigger_multiple, celui-ci va activer le trigger_teleport qui téléportera le joueur :)
Voici l'image. En dessous se trouve le trigger_teleport. Le long bloc vertical est donc le trigger_multiple.
Voilà les paramètres des deux triggers :
Trigger_teleport :
Name : trigger_tele_combine
Start Disabled : Yes
Remote Destination : teleport_destination
Trigger_multiple :
Delay Before Reset : 10
Nous nous occuperons des outputs après. Il faut faire en sorte que quand un joueur se trouve dans le trgigger_multiple, un autre joueur ne puisse pas rentrer. Bah oui, chacun son tour, on fait un téléporteur professionnel, on ne rentre pas comme des bourrins à 20 en même temps !
Pour ça, je vais créer un func_wall_toggle, habillé de toolsinvisible. Mettez-lui wall_tele_combine comme nom, et cochez son flag Starts Invisible.
Pour ajouter du réalise (un téléporteur réaliste ?), on va ajouter deux ambient_generic. Un pour la fermeture du téléporteur, et un autre pour la "mise à feu" du téléporteur.
Voici les paramètres :
Son 1
Name : son_tele_open_combine
Sound Name : ambient/levels/citadel/pod_open1.wav
Max Audible Distance : 1000
Son 2
Name : son_tele_start_combine
Sound Name : ambient/levels/citadel/portal_open1_adpcm.wav
Max Audible Distance : 1000
Pour les deux, cochez les flags Start Silent et Is NOT Looped.
Le petit gars arrive. Il entre dans le trigger_multiple. Ce trigger va alors tout commander. Il commence par dire à model_tele_combine de redéfinir son animation (SetAnimation). Son animation va devenir close. Dans la même seconde, son_tele_open_combine est joué, et wall_tele_combine est activé (Toggle).
A ce stade, les autres joueurs ne peuvent pas rentrer dans le téléporteur. Le joueur en est prisonnier. Après 3 secondes, son_tele_start_combine est joué, et deux secondes plus tard, le téléporteur (trigger_tele_combine) est activé. Le joueur est alors téléporté.
Deux secondes plus tard, le trigger_teleport est re-désactivé, et prêt à être réutilisé. Et pour finir, le téléporteur (model_tele_combine) se réouvre (SetAnimation > open), son_tele_open_combine est une nouvelle fois joué (pour accompagner l?ouverture du téléporteur). Et enfin, wall_tele_combine est togglé, et redevient inactif. Toute la machinerie est prête à fonctionner de nouveau :)
Et voilà, votre téléporteur est fini :) . Prochaine étape : réaliser le même téléporteur que celui du docteur Kleiner, mais ça, je vous laisse faire, je suis fatigué :D .
Dans cette troisième partie apparentée aux déclencheurs, je vais continuer à vous parler des entités de type logic_, que j'appelle des opérateurs, car ils servent à réaliser des opérations comme comparer deux valeurs, appeler une entité aléatoirement...
Je vous ai déjà parlé précédemment des logic_relay (relais d'appels) et de logic_auto (déclenchement automatique au démarrage de la map). Je vais donc vous en expliquer d'autres, globalement moins utiles, mais néanmoins indispensables :) .
Un logic_case est en quelque sorte l'équivalent d'un switch en programmation. Si vous ne connaissez pas, un switch est une condition qui teste toute une série de valeurs. Par exemple, un switch en Javascript ressemble à ceci :
switch(valeur) {
case "1":
// Si valeur vaut 1 alors...
break;
case "thunderseb":
// Si valeur est égale à thunderseb alors...
break;
case "25":
// Si valeur vaut 25 alors...
break;
default:
/ Si valeur n'est égale à aucun des choix précédents...
break;
}
On teste successivement ce que vaut "valeur", et si on trouve, pas exemple que "valeur" vaut 3, on exécute quelque chose. Eh bien avec le logic_case (remarquez le mot "case", qu'on trouve aussi dans le switch ^^ ), on va aussi tester une valeur et voir si elle correspond à des entrées définies.
En programmation (comme dans mon exemple), on peut mettre beaucoup de conditions de test (il n'y en a que 3 dans l'exemple). Mais dans le logic_case, on ne peut en mettre que 16, ce qui est déjà beaucoup ^^ .
Première utilisation : le switch classic
Lors du test du logic_case, si une des "case" (par "case", comprenez chaque propriété CaseXX) correspond à la valeur, l'output correspondant est déclenché. Par exemple, si la "case" 2 est vérifiée, l'output déclenché est OnCase2. Si aucune "case" ne correspond, on peut déclencher l'output OnDefault s'il est spécifié. Cela veut donc dire que vous devez spécifier claque output possible !
Remarquez que vous ne devez pas tout remplir, seulement ce dont vous avez besoin
Pour déclencher le logic_case et débuter le test, il faut utiliser son input InValue (valeur entrante en anglais) en fournissant en paramètre la valeur à tester :
Output named
Targets entities
Via this input
Parameter
Delay
OnTrigger
super_switch
InValue
thunderseb
0.00
La valeur envoyée est donc "thunderseb", ce qui correspond à la deuxième "case" (voir mon image ci-dessus). Cela veut donc dire que c'est l'output OnCase2 qui sera déclenché.
Honnêtement, je n'ai pas d'exemple simple et utile de cette utilisation. Cependant, il existe une deuxième utilisation du logic_case qui se révèle beaucoup plus intéressante !
Deuxième utilisation : le switch aléatoire
Une autre utilisation du logic_case consiste à ne pas renseigner les propriétés CaseXX mais seulement les différents outputs OnCaseXX.
Mais comment s'effectue le test des conditions ?
Il n'y a pas de test. Nous n'allons plus utiliser l'input InValue pour déclencher le logic_case, nous allons utiliser l'input PickRandom, qui signifie Choisir aléatoirement . Cela veut donc dire que parmi les différents outputs définis du logic_case, un de ces outputs va être choisi et déclenché.
Et ici, j'ai un exemple concret à vous donner ! (hou que je suis content ^^ ). Imaginez, vous débutez devant 4 portes, et une seule de ces portes est ouverte. Mais la porte qui s'ouvre n'est pas toujours la même. Le but est donc de choisir, au début de la map, quelle porte sera ouverte. Ainsi le joueur aura une petite "surprise" à chaque commencement.
Pour mettre cette idée en oeuvre, il suffit de mettre un logic_auto (souvenez-vous, je vous en ai déjà parlé) qui appelle le logic_case, lequel choisira entre 4 outputs différents (1 pour chaque porte). Voici ce que ça peut donner :
Output named
Targets entities
Via this input
Parameter
Delay
OnMapSpawn
super_switch
PickRandom
<none>
0.00
Output named
Targets entities
Via this input
Parameter
Delay
OnCase01
porte_01
Open
<none>
0.00
OnCase02
porte_02
Open
<none>
0.00
OnCase03
porte_03
Open
<none>
0.00
OnCase04
porte_04
Open
<none>
0.00
Logic_branch
Le logic_branch est une entité qui vérifie si une valeur est booléenne. Si vous faites de la programmation, le mot "booléen" vous dit certainement quelque chose. Si ce n'est pas le cas, je vais vous l'expliquer brièvement :) .
Une valeur booléenne (boolean en anglais) est une valeur qui peut être soit vraie soit fausse c'est à dire true ou false en anglais ou encore 1 ou 0 en électronique ou en logique.
Les valeurs à utiliser avec un logic_branch sont 0 (pour false) et 1 (pour true).
Donc le logic_branch analyse une valeur pour savoir si elle est vraie ou fausse, et en fonction du résultat du test déclanche ou output :
OnTrue : si la valeur est vraie (si c'est 1);
OnFalse : si la valeur est fausse (si c'est 0).
Mais comment utiliser cette entité ?
L'entité est simple à mettre en oeuvre mais, je le concède, un peu tordue à comprendre ^^ . Je vais vous expliquer son fonctionnement par le biais d'un exemple :) .
Vous souvenez-vous du func_brush ? Pour rappel, c'est un bloc que l'ont peut afficher ou masquer. Il est censé remplacer son homologue func_wall_toggle qui permet là même chose. Mais le func_wall_toggle a quelque chose en plus, il peut être masqué s'il était affiché, et affiché s'il était masqué (d'où son nom "toggle").
En fait, grâce au logic_branch, je vais reproduire le comportement "toggle" du func_wall_toggle avec un func_brush. !
Ce qu'il faut, c'est changer la valeur du logic_branch et l'état du func_brush à chaque fois que le test est effectué. Pour cela, posons que quand le func_brush est affiché la valeur du logic_branch est 1, et s'il est masqué, la valeur est 0.
Commençons par définir les deux outputs du logic_branch qui changent l'état du func_brush. Comme le mur est affiché par défaut, mettez la valeur 1 dans la propriété Value du logic_branch.
Output named
Targets entities
Via this input
Parameter
Delay
OnTrue
murtoggle
Disable
<none>
0.00
OnFalse
murtoggle
Enable
<none>
0.00
Grâce à ça, dès que le test est effectué, si il vaut true ça veut dire que le mu est affiché, donc on souhaite le masquer. C'est le contraire s'il vaut false. Évidemment ça ne marche qu'une fois, puisque nous n'avons pas changé la valeur. C'est pour cela que nous allons ajouter deux autres outputs, qui appellent le logic_branch (que j'ai nommé branch) (l'entité s'auto-appelle ^^ ) :
Output named
Targets entities
Via this input
Parameter
Delay
OnTrue
branch
SetValue
0
0.00
OnFalse
branch
SetValue
1
0.00
Et voilà, votre func_brush est devenu un func_wall_toggle ^^ . Bien sûr si vous mettez un bouton pour faire apparaître/disparaître le mur, vous devez appeler le logic_branch, et non le func_brush en utilisant l'input Test, comme ceci :
Les deux entités dont je vais vous parler maintenant permet de comparer deux valeurs numériques. Je ne vais pas trop m'attarder sur cette entité, car la probabilité que vous l'utilisiez est vraiment très faible (ou plutôt, c'est une excuse parce que je n'ai pas trouvé d'exemple de leur utilisation ^^ ).
Le logic_compare permet de comparer une valeur à une autre et de déclencher 4 outputs :
OnEqualTo : si les deux valeurs sont égales
OnGreaterThan : si la valeur à comparer est plus grande que la valeur de référence
OnLessThan : si la valeur à comparer est plus petite que la valeur de référence
OnNotEqual : si les deux valeurs sont différentes (un mix de OnGreaterThan et de OnLessThan quoi ^^ ).
La valeur de référence (ou la valeur de comparaison) se défini dans la propriété Compare Value. La propriété Initial Value est la valeur à comparer, c'est à dire celle qui sera opposée à la Compare Value (valeur de comparaison).
Bien évidemment il y a des inputs pour modifier ces deux valeurs (attention à ne pas les mélanger ^^ ) :
SetValue : pour re-définir la valeur à comparer (la propriété Initial Value donc)
SetCompareValue : pour re-définir la valeur de comparaison (la propriété Compare Value)
Il y a aussi deux manière de déclencher la comparaison :
Compare : le nom parle de lui-même ^^
SetValueCompare : ça a le même effet que l'input SetValue, mais après avoir re-défini la valeur, le processus de comparaison est enclenché
Permet déclencher des évènements en fonction du temps
Le logic_timer est une entité assez intéressante. Elle permet de déclencher des outputs à intervalles de temps réguliers ou irréguliers (aléatoire).
Pour vous expliquer son utilisation, je vais l'utiliser pour jouer un son d'ambiance bien sympa comme... le cris d'un Fast Zombie dans la nuit noir et brumeuse de Ravenholm :D .
Le principe est vraiment très simple. Un logic_timer va appeler un ambient_generic après un laps de temps aléatoire.
Commencez par placer votre ambient_generic et utilisez le son NPC_FastZombie.AlertFar. Pensez aussi à cocher le flag Play everywhere. Pour mon exemple je vais nommer cette entité "crifastzombie" (je sais, c'est original ^^ ).
Maintenant, au tour du logic_timer. Comme vous devriez déjà l'avoir remarqué, il n'y a pas énormément de propriétés. Comme nous allons jouer le son à intervalles irréguliers, mettez Yes pour la propriété Use Random Time. Il s'agit ensuite de définir les propriété Minimum et Maximum Random Time. Une valeur comprise, en secondes, entre ces deux valeurs sera utilisée comme temps aléatoire.
Maintenant ajoutons un petit output pour jouer le son :
Output named
Targets entities
Via this input
Parameter
Delay
OnTimer
crifastzombie
PlaySound
<none>
0.00
J'utilise l'output OnTimer qui est exécuté quand le temps (aléatoire ou non) est atteint. Il existe aussi deux autres outputs, OnTimerHight et OnTimerLow qui sont déclenchés respectivement quand le temps le plus haut est atteint et quand le temps le plus bas est atteint. Ça n'a bien sûr pas d'intérêt ici.
Voilà, c'est prêt :) . Une longue complainte de zombie viendra égayer votre map ^^ .
Pour terminer, quelques inputs qui peuvent être utiles :
RefireTime : pour re-définir la propriété Refire interval
FireTimer : déclenche immédiatement le timer. Ça appelle en fait son output OnTimer, sans tenir compte de l'intervalle de temps (à utiliser si vous êtes pressé ^^ )
LowerRandomBound : pour re-définir le temps minimum
UpperRandomBound : pour re-définir le temps maximum
Je pense que vous avez une petite idée de ce que nous allons étudier ici :) . Souvenez-vous du chapitre dans la cité minière de Ravenholm, rappelez-vous de l'odeur des zombies cramés et de leurs cris d'agonie ^^ . Nous allons parler des firetraps, ces systèmes qui permettent d'ouvrir le gaz, de l'embraser et de brûler tout ce qui passe :pirate:
Réaliser un firetrap n'est pas spécialement difficile; ça fait juste intervenir assez bien d'entités. Vous en connaissez certaines, et vous allez en découvrir de nouvelles. A la fin de ce mini-tuto, vous saurez créer un départ de feu, des flammes, un effet de gaz qui s'échappe, et nous reverrons aussi les logic_relay, les func_rot_button et les ambient_generic, bref, de l'amusement en perspective :) .
On va maintenant mettre en place les entités, mais sans s'occuper des outputs, juste le placement et le paramétrage.
Les func_rot_button
Pour faire tourner le bouton rouge et la vanne de gaz, on va utiliser des func_rot_button. Vous savez comment ça marche, donc ça ira vite ^^ .
Créez, avec la texture invisible, vos deux boutons rotatifs. Voici les paramètres que je vous suggère :
Bouton rouge
Name : firetrap_boutonrouge
Speed : 200
Sounds : Squeaky
Delay Before Reset : 1
Distance : 90
Cochez les flags Not Solid, Y Axis (ou un autre, ça dépend d'orientation de votre bouton) et Use Activates.
Vanne de gaz
Name : firetrap_vannedegaz
Speed : 200
Sounds : Squeaky
Delay Before Reset : 3
Distance : 360 (un tour complet, pour que ce soit bien ouvert ^^ )
Cochez les flags Not Solid, Toggle (pour pouvoir fermer et ouvrir) et Use Activates.
Les étincelles
Souvenez-vous des étincelles, l'entité env_spark. Il va falloir placer un env_spark à l'extrémité de chaque bec Bunsen, avec les mêmes paramètres, à savoir :
Name : firetrap_spark
Magniture : Medium
Spark Trail Length : Long
Les env_steam
env_steam est une nouvelle entité. Elle permet de créer un jet de vapeur. Nous allons l'utiliser pour représenter les jets de gaz qui sortent des bec Bunsen :) . On mettra donc une de ces entités à chaque sortie de bec Bunsen.
L'env_steam est représenté sous la forme d'un cône. Le sommet symbolise le point de départ du gaz, et la base indique dans quel sens le jet est projeté, ce qui est plutôt pratique pour bien positionner l'entité. Comme c'est une nouvelle entité, je vais vous lister ses propriétés, les expliquer, et donner les valeurs adéquates dans le cas de notre jet de gaz incolore :) .
Name : firetrap_vapeur
Initial State : état initial de l'entité. Mettez Off
Particule Type : : type de particule qui est projeté :
Normal : un gros jet gras ^^
Heat Wave : un effet vague de chaleur, comme sur les autoroutes quand il fait chaud.Choisissez cette option, ça donnera un bel effet flou
Spread Speed : vitesse de dissociation des particules. Il faut comprendre que c'est la vitesse à laquelle les particules s'éloignent les unes des autres. En mettant une valeur de 15, le jet reste relativement compact
Speed : vitesse de sortie du jet de gaz. Mettez 200
Particule start size : taille des particules au début du jet. Mettez 10
Particule end size : taille des particules à la fin du jet. Mettez 20
Emisson rate : fréquence d'émission des particules. Une valeur de 25 est acceptable
Color : couleur du jet. Prenez une teinte orangée ( 239 194 61 ), mais si ça n'a pas beaucoup d'importance, puisqu'on va rendre le jet transparent ^^
Length of steam jet : longueur du jet. Une longueur de 80 convient largement
Translucency : transparence. Laissez 255
How fast does the particles spin : (pour Episode One) vitesse de rotation des particules. Laissez 8
Les départs de feu
Il existe une entité pour créer une flamme, nous la verrons juste après, et il existe aussi une entité pour créer un effet d'embrasement. Cette entité se nomme env_firesource. Placez également une de ces entités à la sortie de chaque bec Bunsen (près des env_spark, ce qui est logique).
Name : firetrap_firesource
Radius : 60
Le brasier
Nous voici enfin aux flammes ^^ . L'entité utilisée pour en créer une est env_fire (remarquez que le nom des entités correspondent souvent à leur fonction ^^ ).
Name : firetrap_fires
Start Disabled : Yes
Duration : temps que brûle la flamme. Mettez ce que vous voulez, car on cochera le flag Infinite Duration ^^
Sire : taille de la flamme. Voyez ma remarque plus bas...
Attack : vitesse à laquelle la flamme grandit pour aboutir à sa taille maximale (Size). Ca doit être rapide, c'est du gaz. Mettez 0.05
Type : type de flamme. Laissez bien Naturel, on n'a pas besoin d'un effet plasma
Ignition point : position du point d'ignition. Mettez 1, la flamme est au sol ^^ .
Damage Scale : mettez 10 pour multiplier par 10 les dommages causés par la flamme
Cochez aussi le flag Smokeless, pour ne pas créer trop de fumée. On fait un simple brasier, pas un incinérateur ^^ .
Pensez à mettre un Size décroissant sur les env_fire. Près des becs Bunsen, mettez une Size de 110, et descendez jusqu'à 80 pour les flammes les plus éloignées de ce bec. Ça donne un effet de réel, car il y a plus de gaz près des becs, donc de plus grandes flammes ;) .
Les ambient_generic
On va ajouter plusieurs sons, au moyen d'ambient_generic. Il n'y a pas de réglages particulier, hormis le nom de l'entité, le son à jouer et quelques flags. Je vous ai fait un tableau pour présenter ça proprement :
Name
Emplacement
Son
Explications
Flags cochés
firetrap_vapeur_son
Au centre des flammes
ambient/gas/steam_loop1.wav
Son que fait le gaz en sortant des becs Bunsen
Start Silent
firetrap_firestart_son
Au centre des flammes
d1_town.FlameTrapIgnite
Son joué quand le gaz s'embrase
Start Silent, Is Not Looped
firetrap_fires_son
Au centre des flammes
d1_town.LargeFireLoop
Le bruit que fait le brasier
Start Silent
firetrap_firestop_son
Au centre des flammes
d1_town.FlameTrapExtinguish
Son joué quand on coupe le gaz et que les flammes s'éteignent
Start Silent, Is Not Looped
firetrap_boutonrouge_son
Près du bouton rouge
Town.d1_town_01_lightswitch2
Bruit du bouton (une sorte de clic sourd). Pensez à mettre une distance d'audition faible
Start Silent, Is Not Looped
Pour finir...
On va aussi ajouter un petite light qu'on allumera en même temps que les flammes, pour appuyer l'éclairage de ces flammes :)
Name : firetrap_light
Brightness : 254 174 10 500
Et cochez le flag Initialy Dark.
Voici une image de ce que j'obtiens. Vous devriez avoir sensiblement la même chose :
Ce que j'obtiens. Remarquez que les env_steam, les env_firesource et les env_spark sont au même endroit sur chaque bec
Attaquons-ous maintenant au codage des outputs ; ce n'est pas difficile, mais ça demande de la logique :) .
Histoire de nous simplifier la tâche, nous allons créer deux logic_relay : un pour démarrer l'embrasement, et un autre pour y mettre fin. Nommez respectivement ces deux entités firetrap_relay_start et firetrap_relay_end. Laissez la propriété Start Disabled sur Yes.
On y reviendra plus tard. On va commencer par les outputs de la vanne de gaz.
La vanne de gaz
Output named
Targets entities
Via this input
Parameter
Delay
OnIn
firetrap_vapeur
Toggle
<none>
0.00
OnIn
firetrap_relay_start
Enable
<none>
0.00
OnIn
firetrap_vapeur_son
ToggleSound
<none>
0.00
J'utilise l'output OnIn, qui a pour effet d'être déclenché dès qu'on pose les mains sur la vanne (dès qu'on presse E ^^ ). Comme ça, dès qu'on commence à tourner, ça se déclenche. Donc, dès qu'on pose les mains, on actionne/arrête les jets de vapeur (firetrap_vapeur), ainsi que leur bruit (firetrap_vapeur_son). J'active aussi le logic_relay de départ de feu (firetrap_relay_start). Mais attention, il est activé, pas déclenché !
On le déclenchera quand on tournera le bouton rouge. Ce stratagème nous empêche de déclencher le logic_relay sans avoir ouvert le gaz avant (puisque dans ce cas, le logic_relay n'aurait pas été activé).
Maintenant, on va ajouter les outputs quand on lâche la vanne (on vient de de la refermer) :
Output named
Targets entities
Via this input
Parameter
Delay
OnOut
firetrap_vapeur
Toggle
<none>
0.00
OnOut
firetrap_relay_start
Disable
<none>
0.00
OnOut
firetrap_relay_end
Trigger
<none>
0.00
OnOut
firetrap_vapeur_son
ToggleSound
<none>
0.00
Donc là, rien de bien compliqué. On annule tout ce qui a été fait avec OnIn. On fait appel au relais firetrap_relay_end, qu'on déclenche (il sera activé par le relais de démarrage du feu).
Le bouton rouge
Ici, il n'y a que 3 outputs très simples :
Output named
Targets entities
Via this input
Parameter
Delay
OnIn
firetrap_boutonrouge_son
PlaySound
<none>
0.00
OnIn
firetrap_spark
SparkOnce
<none>
0.00
OnIn
firetrap_relay_start
Trigger
<none>
0.00
Très simple. On joue le son du bouton, on actionne les étincelles une fois (SparkOnce) et on déclenche le logic_relay qui va à son tour déclencher le brasier :) .
Le relais de départ
On va enfin s'occuper du firetrap_relay_start. On va activer les env_firesources, les env_fire. On active aussi firetrap_relay_end, et on désactivé le firetrap_relay_start (il s'auto-désactive ^^ ). On en profite aussi pour allumer la light, 0.5 secondes après :) .
Output named
Targets entities
Via this input
Parameter
Delay
OnTrigger
firetrap_firesource
Enable
<none>
0.00
OnTrigger
firetrap_relay_end
Enable
<none>
0.00
OnTrigger
firetrap_fires
Enable
<none>
0.00
OnTrigger
firetrap_relay_start
Disable
<none>
0.00
OnTrigger
firetrap_firestart_son
PlaySound
<none>
0.00
OnTrigger
firetrap_light
TurnOn
<none>
0.50
Le relais de fin
Output named
Targets entities
Via this input
Parameter
Delay
OnTrigger
firetrap_firesource
Disable
<none>
0.00
OnTrigger
firetrap_firestop_son
PlaySound
<none>
0.00
OnTrigger
firetrap_relay_end
Disable
<none>
0.00
OnTrigger
firetrap_fires
Extinguish
1
0.20
OnTrigger
firetrap_fires
Disable
<none>
1.20
OnTrigger
firetrap_light
TurnOff
<none>
0.35
Donc ici, on fait quasiment le contraire de ce qui a été fait avec le relais de départ. On annule tout, et on s'auto-désactive. Remarquez l'input plutôt particulier que possèdent les env_fire : Extinguish. C'est un input qui permet de réduire progressivement la taille des flammes à 0, en fonction de la vitesse en paramètre. Nous avons mis 1, pour que les flammes mettent une seconde à mourir, ce qui accentue un peu le réalisme :) .
Oui, mais on n'a pas parlé du bruit que font les flammes, on l'oublie ?
Non non non, on va le déclencher, mais pas avec les logic_relay. On va utiliser un détecteur de chaleur pour savoir si les flammes brûlent ou ne brûlent pas :) . De cette manière, le son sera joué exactement quand le brasier sera actif !
Pour ça, on va utiliser l'entité env_firesensor. Placez cette entité au centre des env_fire (au même endroit que les ambient_generic). Voici les paramètres :
Name : on ne met rien, pas besoin de l'appeler
Radius : 40
Heat level : niveau de chaleur. Laissez 32 degrés
Time at level : le temps avant de déclencher l'entité dès que la chaleur a atteint le Heat level. Laissez 0
Quand le niveau de chaleur est dépassé, l'output OnHeatLevelStart est déclenché. Quand le seuil redescend, c'est OnHeatLevelEnd qui est appelé. On va donc utiliser ces deux outputs pour jouer/muter le son :
Output named
Targets entities
Via this input
Parameter
Delay
OnHeatLevelStart
firetrap_fires_son
PlaySound
<none>
0.00
OnHeatLevelEnd
firetrap_fires_son
StopSound
<none>
0.00
Voilà, ce n'est pas bien compliqué :) .
Ehhh, mais dans Ravenholm, quand on tire dans le gaz, ça s'embrase. Or ici, çe ne marche pas. Pourquoi ?
Parce qu'on n'a rien mis pour détecter le shoot ^^ .
J'ai pensé à une méthode simple pour faire ça. Je mets un func_button avec la texture nodraw sur le sol, et qui recouvre toute la surface des flammes. Ce bouton fait une unité de haut et est plaqué au sol. Le paramètre de façon à ce qui ne se passe rien de spécial, hormis si on tire dessus. Pour ça, je mets la propriété Health sur 2, et je coche le flag Damage Activates. Pour savoir si on a tiré sur le bouton, j'utilise cet output :
Les maps dans lesquelles il pleut ou il neige ne sont pas fréquentes. Pourtant, ça peut donner un bel effet :) .
Pour mettre de la pluie ou de la neige dans votre map, vous devez utiliser l?entité-bloc func_precipitation (le nom est très en rapport avec la fonction ^^ ). Vous devez créer un bloc, avec la texture toolstrigger qui recouvre toute votre map. La pluie sera ajoutée dans ce bloc. Transformez le bloc en func_precipitation.
Et les maisons ?
Ce n?est pas grave, remplissez tout. Vous verrez qu?il ne pleuvra ou ne neigera pas dans les maisons ;) .
Density : c?est la densité de la pluie. Ne vous ennuyez pas et laissez la valeur par défaut, c?est très bien
Color : couleur de la pluie. Laissez blanc, je n?ai jamais vu de pluie verte ^^
Precipitation Type : mettez Rain. Vous pouvez aussi mettre Snow si vous voulez de la neige.
L'utilisation des func_precipitation
Je vous ai dit de créer un gros bloc qui recouvre votre map. Si votre map est parfaitement carrée, c'est une bonne solution. Mais si elle ne l'est pas, vous pouvez bien évidemment créer plusieurs blocs func_precipitation. Si vous mettez plusieurs blocs, essayez de faire en sorte qu'ils aient tous plus ou moins la même taille car la densité des précipitations est calculée en fonction du volume du bloc. Donc pour essayer d'avoir la même densité de pluie ou de neige partout, faites des blocs de la même taille, ce sera plus simple.
Valve donne quelques recommandations à propos de l'utilisation des func_precipitation. Je vais vous les lister ici.
Vous devez éviter de mettre des précipitations si votre map contient de l'eau. Ou tout du moins, vos précipitations ne doivent pas entrer en contact avec l'eau. Ça peut provoquer des crashs de la map et ou du jeu
Evitez aussi de mettre une densité trop élevée. C'est possible de le faire, mais risqué. Ça peut provoquer des ralentissements ou même un crash.
Les précipitations ne peuvent en aucun cas sortir de la map ! Pour cela, évitez de coller vos func_precipitation aux murs de limite de votre map. En effet, les précipitations peuvent sortir légèrement hors de l'espace du bloc func_precipitation, et elles pourraient se retrouver hors de la map. Prudence donc ^^ .
Valve dit aussi que les précipitations ne doivent pas entrer dans un func_smokevolume. Je vous expliquerai cette entité plus bas dans cette partie. Il faut donc laisser un "trou" au milieu de vos func_precpitation pour y placer le func_smokevolume.
Permet de mettre en place une propagation constante de fumée
Rien de tel que de mettre une cheminée sur vos maisons et d'en faire sortir un nuage de fumée. Un entité se prêt particulièrement bien pour créer cette fumée : env_smokestack.
Cette entité produit un nuage de fumée à partir de son origine (l'emplacement de l'env_smokestack) et qui se disperse tout doucement dans l'air, exactement comme la fumée qui sort d'une cheminée. Regardez ce que ça donne :
Mais pour que ce soit réaliste, il s'agit de bien placer l'entité. Sur le screen ce-dessous, je place l'entité "dans la buse" de la cheminée, pour qu'il n'y ait pas d'espace entre le début de la fumée et la sortie de la cheminée :
Voici les quelques propriétés utiles :
Initial State : mettez On pour que la fumée soit émise par défaut
Spread at the base : vitesse de dispersion de la fumée à la base du smoketrack
Spread Speed : vitesse de dispersion de la fumée
Speed Speed : vitesse de propagation de la fumée à la base du smoketrack
Particle start size : taille des particules lors au début de l'émission (à la base du smoketrack donc)
Particle end size : taille des particules à la fin de l'émission, au moment où elles commencent à disparaître
Emission rate : particules émises par seconde. C'est la densité d'émission
Length of smoke trail : longueur de l'émission de fumée. Laissez la valeur par défaut, comme sur mon screenshot.
Wind X/Y Angle : c'est l'angle démission. Mettez 10 ou 15 pour incliner légèrement
Wind Speed : la force du vent qui fera dévier la fumée. Ici encore, une valeur de 10 ou de 15 est acceptable.
Twist : vitesse de rotation des particules autour de l'origine. C'est pour faire un effet tornade. Mettez une valeur faible comme 2 ou 5 ; vous faites de la fumée, pas un cyclone ^^
Base Color (R G B) : couleur de la fumée. Dans mon exemple j'ai pris 129 129 129
Translucency : transparence de la fumée. Mettez 150 ou 180 pour un rendu plus ou moins opaque
Permet de créer un volume dans lequel évolue de la poussière dense
Le vent
Par défaut le vent ne souffle pas. Mais pour créer un ambiance et ajouter du réalise, il peut-être utile de le faire souffler pour, par exemple, faire balancer légèrement des câbles.
La méthode traditionnelle pour faire souffler le vent est d'insérer un env_wind qui va servir à paramétrer le vent qui soufflera sur toute la map. La deuxième solutions consiste à utiliser un trigger_wind. C'est un volume dans lequel le vent va souffler. Ça vous permet de faire des petits effets par-ci par-là sans toucher à la configuration du vent qui souffle sur la totalité de la map (paramétré avec l'env_wind).
L'env_wind possède moins d'inputs que le trigger_wind. Il n'est par exemple pas possible d'activer ou de désactiver le vent. Je vais vous donner les propriétés de l'env_wind. Puis dans un exemple je vous introduirais le trigger_wind pour faire des rafales avec une envolée de particules.
Min normal speed : vitesse minimale du vent
Max normal speed : vitesse maximale du vent
Min gust speed : vitesse minimal des rafales
Max gust speed : vitesse maximale des rafales
Min gust delay : délai minimum entre deux rafales
Max gust delay : délai maximum entre deux rafales
Gust Duration : durée des rafales
Max gust dir change (degrees) : nombre de degrés dont les rafales font changer la direction du vent
Deux outputs intéressants ont été implémentés avec Half-Life² Episode 1 :
OnGustStart : quand une rafale commence
OnGustEnd : quand une rafale se termine
C'est mieux avec des bourrasques
Le vent va souffler par rafales et à chaque rafale on va faire comme si le vent faisait se soulever des particules, comme du sable, de la terre. Comme ceci, le premier screen au repos et le deuxième avec une bourrasque qui provoque un soulèvement de poussière (c'est une légère bourrasque pas une tempête de sable, donc c'est assez léger) :
Avant la rafale -> Pendant la rafale
Pour faire ce genre de chose il faut :
un logic_timer qui activera les bourrasques de façons aléatoire
un func_dustcloud pour générer le nuage de particules
un trigger_wind pour souffler dans le func_dustcloud
un ambient_generic pour jouer le son du vent qui souffle
Vous pouvez utiliser le son ambient/wind/windgust_strong.wav pour l'ambient_generic. Voici comment j'ai placé le trigger_wind et le func_duscloud. Ce dernier est plus petit et qui est placé dans le trigger_wind :
Le trigger_wind
Mettez sa propriété Start Disabled sur Yes pour ne pas qu'il soit actif dès le début, et mettez une vitesse de 120 (propriété Speed). Spécifiez aussi un point d'origine et un angle pour définir la direction du vent.
Le func_dustcloud
Pareil que pour le trigger_wind, mettez Yes pour Start Disabled. Spécifiez une couleur, si possible une couleur qui se rapproche de celle du sol que vous utilisez. Voici les autres propriétés :
Particle Per Second : nombre de particules par seconde. 30 semble être une bonne valeur.
Maximum Particle Speed : vitesse des particules
Minimum Particle Lifetime : temps minimum de vie des particules.
Maximum Particle Lifetime : temps maximum de vie des particules.
Maximum Visible Distance : distance maximale dans laquelle les particules sont visibles.
Frozen : laissez sur No. Si vous mettez Yes, les particules apparaîtront mais ne bougeront pas.
Alpha : valeur de transparence. Plus c'est élevé, plus c'est opaque. Mettez 30.
Minimum Particle Size : taille minimale des particules. Mettez une valeur faible genre 5 ou 10.
Maximum Particle Size : taille maximale des particules. Mettez aux alentours de 50 ou 60.
Le logic_timer
Pour le logic_timer, mettez le en position aléatoire (Use Random Time sur Yes). Définissez Minimum et Maximum Random Interval avec respectivement 7 et 14.
Puis, définissez les outputs comme ceci :
Output named
Targets entities
Via this input
Parameter
Delay
OnTimer
dustcloud
TurnOn
<non>
0.00
OnTimer
ambientgeneric
PlaySound
<non>
0.25
OnTimer
triggerwind
Enable
<non>
0.25
OnTimer
dustcloud
TurnOff
<non>
5.00
OnTimer
triggerwind
Disable
<non>
5.25
Tout s'arrête après 5.25 secondes. Il est donc important d'avoir choisi un Minimum Random Interval (pour le logic_timer) plus grand que 5, sinon deux rafales pourraient être déclenchées en me^me temps, ce qui provoquerait certainement autre chose que ce qui est souhaité ^^ .
L'env_fog_controller est une entité qui permet de mettre du brouillard et de le paramétrer. Le brouillard a en réalité deux utilisations :
pour faire joli
pour optimiser
On utilise le brouillard pour optimiser les grandes maps car il est possible de faire disparaître les zones que le brouillard masque ce qui permet de soulager le moteur graphique et de gagner de précieux FPS en plus ! En général, si on utilise un env_fog_controller pour optimiser, c'est que les autres techniques d'optimisation se sont révélées vaines.
Voici un exemple de map ou le brouillard est utilisé pour optimiser. La map dod_snowblind de Grippy est une map très vaste et le brouillard permet de réduire la profondeur de visibilité et ainsi que masquer tout ce que le brouillard cache :
dod_snowblind de Grippy
Placer l'env_fog_controller
Placez l'entité où vous voulez dans votre map, cela n'a pas d'importance. L'env_fog_controller possède un certain nombre de propriétés mais seules 5 sont vraiment utiles :
Fog Enable : mettez Yes pour activer le brouillard
Primary Fog Color : c'est la couleur du brouillard. Vous pouvez aussi spécifier une Secondary Fog Color mais ce n'est pas nécessaire.
Fog Start : distance à laquelle le brouillard commence
Fog End : distance à laquelle le brouillard se termine. On n'y voit plus rien, c'est totalement opaque.
Far Z Clip Plane : voir ci-dessous
Par défaut, les éléments qui sont cachés par le brouillard sont quand même affichés, ce qui fait que si vous utilisez l'entité dans le but d'optimiser, elle ne sert à rien ^^ . Pour faire disparaître les éléments masqués par le brouillard il faut spécifier la distance à partir de laquelle le jeu ne doit pas afficher les éléments. C'est à ça que sert la propriété Far Z Clip Plane. Mettez y la même valeur que la propriété Fog End, comme ça dès que le brouillard est opaque, ce qui est derrière n'est plus affiché.
L'entité game_text permet d'afficher une portion de texte à l'écran du ou des joueurs. Ça peut être pratique pour afficher un petit "Have fun" avant de commencer une partie ^^ . Vous pouvez aussi, dans une partie solo, l'utiliser pour donner des informations au joueur.
Pour utiliser l'entité, il suffit de la placer où vous voulez, de lui donner un nom et de l'appeler au moment voulu, au moyen de son input Display. Voici d'ailleurs une vue d'ensemble de ses propriétés :
Message Text : c'est le message à afficher. C'est très simple comme texte, pas de retours à la ligne, d'alinéas... Vous devez éviter de mettre des apostrophes typographiques ( " ) et des anti-slash ( \ ), car ça peut provoquer des crash lors de la compilation ou de l'exécution de la map (c'est Valve qui le dit, je fais confiance moi ^^ ). Mais vous pouvez utiliser des apostrophes typographiques gauche et droite (? et ?).
X : c'est la position horizontale, en partant de la gauche. Mettez -1 si vous voulez que le texte soit centré.
Y : c'est la position verticale, en partant du haut. Mettez -1 si vous voulez que le texte soit centré.
Text Effect : c'est l'effet avec lequel le texte sera affiché
Fade In/Out : le texte apparaît progressivement et disparait progressivement. Je vous recommande fortement cette option.
Credits : ressemble au Fade In/Out.
Scan Out : les lettres apparaissent les unes après les autres en ayant un effet de Fade In et en clignotant. C'est très moche ^^ .
Fade In Time : c'est le temps qu'il faut pour que le texte soit complètement affiché.
Fade Out Time : le temps qu'il faut au texte pour disparaître.
Hold Time : le temps que le texte reste affiché (sans compter l'apparition et la disparition).
Scan Time : si vous avez choisi l'effet Scan Out, c'est le temps nécessaire au scanning des différentes lettres
Pensez à cocher ou non le flag All players, si vous souhaitez ou non que tous les joueurs voient le texte ;) .
Permet d'afficher un texte contenu dans un fichier .txt à l'écran
L'env_message est en quelque sorte l'évolution du game_text. Le game_text ne permet que d'afficher une phrase, alors que l'env_message permet d'afficher vrai texte, avec des retours à la ligne. Seulement, cette entité est un brin plus complexe à mettre en ?uvre car il faut créer un fichier .txt qui contiendra le texte à afficher. Mais avant, si vous n'avez encore jamais vu ce que peut donner un env_message, voici le premier message d'information qui s'affiche dans le mod solo Combine Destiny :
Le fichier texte
Le fichier texte se nomme titles.txt et se trouve dans le répertoire votremod/scripts/. Ce fichier contient des messages pouvant être affichés durant le jeu. Les messages sont écrits à la suite, et un nom leur est attribué, comme ceci :
NOM_DU_MESSAGE1
{
Contenu de ce premier message
Et hop, line-break :)
}
NOM_DU_MESSAGE2
{
Contenu de ce 2e message
Gordon est barbu
}
Le problème est qu'il ne peut y avoir qu'un seul fichier titles.txt, ce qui fait que ce système est tout à fait inadapté pour les maps multi et même les maps solo pour HL². Ce système est à utiliser par exemple si vous développez votre propre mini-mod. Imaginez si plusieurs mappeurs définissaient chacun leur titles.txt : à chaque installation de map, l'ancien fichier .txt serait écrasé et son contenu ne correspondrait plus.
Cela dit, si vous faites une map pour HL², vous pouvez vous servir du fichier titles.txt du jeu original et l'utiliser pour afficher les messages qui y sont enregistrés, comme par exemple :
Citation : Half-Life² - Game Over - Try again, if you can ^^
ASSIGNMENT: TERMINATED
SUBJECT: FREEMAN
REASON: FAILURE TO PRESERVE MISSION-CRITICAL PERSONNEL
L'entité
Insérez l'entité env_message, et ouvrez ses propriétés. Dans la propriété Message Text, vous devez mettre le nom du message à afficher. Par exemple, si je veux afficher le deuxième message de mon exemple ci-dessus, je mets NOM_DU_MESSAGE2. Si vous voulez afficher un message d'HL², reportez-vous à la page de l'env_message sur le Wiki de Valve, il y a un tableau avec le nom des messages et leur contenu.
L'input pour afficher le message n'est plus Display comme pour le game_text, mais bien ShowMessage (allez comprendre la logique de Valve ^^ ). Notez aussi que cette entité vous permet de jouer un son en même temps que l'affichage du message. C'est bien entendu facultatif.
Permet d'afficher une portion de texte à un endroit de la map
Le game_text permet d'afficher du texte à l'écran, et le point_message permet, tenez-vous bien, d'afficher du texte dans la map. Le texte affiché est positionné à l'endroit où se trouve l'entité, et est toujours face au joueur (un peu comme un sprite, qui s'oriente en fonction du joueur qui le regarde). Regardez, voici un exemple, encore tiré de Combine Destiny. Les point_message sont utilisés pour définir l'utilité des consoles (consoles qui servent de boutons).
Le point_message n'a pas besoin d'être affiché, il peut s'afficher automatiquement à partir d'une certaine distance (propriété Show Message Radius). Ça évite au joueur qui se trouve à 200 mètres du texte de l'apercevoir ^^ .
Le contenu du message doit bien sur être rédigé dans la propriété Entity Message.
Ici, on ne rigole plus. Il est temps de voir ce que sont les path_track !
Derrière ce nom un peu barbare, se trouve en réalité quelque chose de simple à comprendre (le nom, c'est juste pour effrayer), mais complexe à utiliser. Nous allons tout de suite entrer dans le vif du sujet :) .
path_track est à la fois le nom d'une entité, et à la fois un terme qu'ont les mappeurs pour désigner un moyen de faire bouger des entités en suivant un chemin déterminé.
Un chemin : c'est la clé d'utilisation des path_track. Path veut dire chemin et track, ça veut dire voie.
Les path_track servent à définir un chemin - un itinéraire - par lequel va se déplacer une entité, généralement un func_tracktrain. Dans func_tracktrain, il y a le mot train. Quand on parle de path_track pour désigner le moyen de déplacer des entités, on peut aussi parler de train.
Regardez cette petite mise en situation :
Le joueur doit franchir le passage, sans tomber dans l'eau. Pour ce faire, j'ai créé une plateforme qui se déplacera en suivant l'itinéraire que j'ai tracé en utilisant mes talents de graphiste (le premier kiri... :-° ). Grâce aux path_track, nous allons définir cet itinéraire pour que la plateforme le suive et amène le joueur de l'autre côté.
Permet définir un point de passage pour un "train"
Dans un premier temps, il convient de placer un premier path_track qui fera office de point de départ. Placez-le, si possible, au centre de la plateforme, et donnez-lui comme nom path_0 (soyons geeks, comptons à partir de 0 ^^ ), comme ceci :
Le truc est de placer un path_track à chaque angle pour indiquer à la plateforme qu'elle va devoir changer de direction. Ainsi, dans mon exemple, j'ai besoin de 4 path_track : le départ, le premier angle, le deuxième, et l'arrivée.
Pour placer le deuxième path_track, il y a deux méthodes : une normal, et une super facile pour les faignants. La méthode normale est tout simplement de créer un autre path_track avec l'outil de création d'entités. Il faut ensuite nommer l'entité. La deuxième méthode, ma préférée, consiste à dupliquer le path_track déjà créé (souvenez-vous, vous sélectionnez l'entité, et en maintenant la touche Shift (Majuscule) enfoncée, vous déplacez l'entité). Et c'est là que la fainéantise se dévoile : Hammer renomme automatiquement la nouvelle entité, en ajoutant une unité : path_0 devient donc path_1.
Ouvrez les propriétés de path_0. La propriété Next Stop Target vaut path_1. Cette propriété sert à définir quel sera le prochain path_track que la plateforme devra atteindre. C'est pour ça que la deuxième méthode est pratique, car c'est Hammer qui va s'occuper de définir cette propriété.
Ainsi, de fil en aiguille, en dupliquant à chaque fois le dernier path_track, vous allez créer votre chemin. Vous pouvez vérifier que le chemin est correctement créé en regardant les vues Top et 3D : une ligne relie les différents path_track, comme ceci :
Les propriétés
Il faut savoir que les path_track, en plus d'agir comme des "angles", agissent un peu comme des points de contrôle à partir desquels il est possible par exemple de définir une nouvelle vitesse pour l'élément qui suit le trajet (ici la plateforme).
Les tracks ont donc la propriété New Train Speed qui permet de redéfinir la vitesse du train dès qu'il franchit le point. Une valeur de 0 permet de conserver la vitesse du train (il n'y a donc pas de changement de vitesse).
La propriété Branch Path ressemble à Next Stop Target, mais sert à faire un aiguillage (comprenez, un chemin alternatif au chemin normal). J'y reviendrai avec un exemple.
Orientation Type sert à redéfinir l'orientation que prendra le train :
Face direction of motion : si le path_track dit d'aller à droite, le train va s'orienter pour tourner à droite (il s'oriente en fait face un path_track suivant). C'est le comportement normal d'un honnête train.
No change : la direction reste toujours la même. C'est la valeur que je choisis pour mon exemple, puisque je n'ai pas besoin que la plateforme s'oriente (elle est carrée, et puis ça ne sert à rien ^^ ).
Face this path_track's angles : le train s'oriente en fonction de l'angle du path_track.
Côté flags
Disabled : le path est désactivé, le train ne peut donc pas passer par là. Il faudra donc activer ce path_track avec un input (EnablePath)
Fire once : le train ne peut passer qu'une seule fois sur ce path. Après le passage du train, l'entité est désactivée
Branch reverse : Branch Path fait office de Next Stop target (et à fortiori, Next Stop Target fait office de Branch Path)
Disable train : le train s'arrête sur ce path
Inputs et Outputs
Inputs
Parmi les inputs, en voici quelques-uns qui peuvent se révéler utiles :
ToggleAlternatePath, EnableAlternatePath et DisableAlternatePath : ces inputs permettent de contrôler l'aiguillage. Si vous l'activez, le path spécifié dans la propriété Branch Path sera activé, et le train suivra ce chemin.
TogglePath, EnablePath et DisablePath : ceux-ci permettent, comme vous devriez le deviner, de contrôler l'état du path_track : toggle, activé et désactivé.
Output
Il n'y a qu'un output : OnPass qui est déclenché quand le train passe par le path.
Permet créer un train parcourant un chemin de path_track
Le chemin est mis en place, passons au train (à la plateforme).
Sélectionnez toute votre plateforme, et transformez-la en func_tracktrain.
A l'inverse des path_track, func_tracktrain possède assez bien de propriétés. Comme toujours, leur fonctionnement est généralement simple. Je fais comme d'habitude l'impasse sur les propriétés déjà connues.
Func_tracktrain permet de définir les propriétés globales du train. Les path_track peuvent modifier certaines valeurs (comme la vitesse), mais si par exemple la vitesse maximale du train est fixée à 100 unités/seconde, un path_track ne peut pas définir une nouvelle vitesse de 150 unités/secondes. C'est donc les propriétés du func_tracktrain qui prévalent sur celles des path_track
First Stop Target : une des propriétés les plus importantes : le nom du path_track de départ. Mettez donc path_0 pour coller à mon exemple.
Max Speed : la vitesse maximale du train.
Initial Speed : la vitesse initiale du train. 0 = arrêt.
Change Velocity : c'est la façon dont le train change de vitesse, si une nouvelle vitesse est spécifiée dans le path_track qu'il traverse. Je vous conseille de laisser Instantaneously.
Change angles : changement de direction. Mettez Never pour que le train ne change pas de direction à chaque part_track. Cette propriété prévaut donc dur les propriétés Orientation Type des path_track
Distance Between the Wheels : la distance entre les roues de devant et celles de derrière. Si vous faites un "vrai" train (un wagonnet sur des rails par exemple), cette valeur est importante et permet au moteur Source de mieux gérer les tournants. Ici, c'est pas important. Si vous avez dur de mesurer la distance, mettez la longueur du train, et ça devrait marcher :) .
Height above track : la distance entre le train et les "rails" (si on voit des rails, ce qui n'est pas le cas dans notre exemple).
Bank Angle on Turns : le degré d'inclinaison du train quand il prend un tournant. Laissez 0, le moteur Source saura bien se débrouiller seul ^^ .
Les autres propriétés sont en rapport avec le bruit de train, c'est facile à comprendre :) .
Voici maintenant quelques flags :
No Pitch : le train ne tangue pas (il ne balance pas de gauche à droite dans les tournants).
No User Control : le train n'est pas contrôlable par le joueur (avec un func_traincontrols). <puce>Passable : le joueur passe au travers.
Fixed orientation : l'orientation est toujours la même. J'ai coché ce flag pour mon exemple.
Comme mon train est arrêté par défaut (Initial Speed valant 0), il faut que le train démarre quand le joueur se positionne dessus. Pour cela, rien de plus facile : un trigger_once qui déclenche le démarrage (en marche avant du train : StartForward) du train :
Voici quelques inputs utiles :
Stop : stoppe le train
StartForward : démarre le train, en marche avant
StartBackward : démarre le train, en marche arrière
Resume : redémarre le train s'il avait été stoppé (le contraire de Stop en fait)
Je vous ai parlé du Branch Path qui permet de spécifier un chemin alternatif à un path_track. Nous allons donc le mettre en pratique pour faire un l'itinéraire pourvu d'un aiguillage. Voici la maquette :
L'aiguillage se fait donc sur le path_2. Sa propriété Branch Path pointe sur le premier path_track du petit chemin dans le bas à gauche de l'image.
J'ai créé un trigger_once (le bloc sélectionné sur l'image). Si le joueur le traverse, le chemin alternatif est activé, et le train sera aiguillé vers la deuxième sortie, en suivant ma jolie flèche verte. L'output est défini de cette façon :
Output named
Targets entities
Via this input
Parameter
Delay
OnTrigger
path_2
EnableAlternatePath
<none>
0.00
Reportez-vous à la première partie pour les inputs des path_track ;) .
Il est possible de faire un train qui tourne en rond, qui n'a pas de fin. Ca peut être pratique ^^ . Faire ce genre de truc est très très simple puisqu'il suffit de connecter le dernier path_track du chemin au path_track de départ. Ainsi, quand le train passe par le dernier path, il est dirigé vers le premier, et le cycle recommence :) :
Le va-et-vient
Si vous avez joué à Portal, vous devez certainement comprendre d'où vient mon inspiration pour les plateformes qui se déplacent ^^ . Si vous n'avez pas joué à Portal, sachez qu'il y a plusieurs épreuves qui se déroulent en utilisant des plateformes de ce type. Il y a aussi une autre version de la boucle infinie qui consiste à faire bouger la plateforme d'un point A vers un point B, puis du point B vers le point A. Bref, la plateforme fait continuellement un aller-retour entre les deux extrémités du chemin :
Il n'y a pas de secret, ça fonctionne exactement comme la boucle infinie. Le point A pointe vers B, et B pointe vers A :) .
Des utilisations des path_track, il y en a des tonnes.
L'utilisation de base est de faire des trains, mais j'ai choisi de vous les enseigner avec des plateformes. C'est un choix discutable, mais ça me permettait de faire des schémas simples, des mises en situation simples et d'avoir une configuration minimale.
Le must est d'utiliser les path_track pour faire un train qui accélère sur une longue distance, qui ralentit dans un tournant et qui reprend de la vitesse après. D'ailleurs, en parlant de tournants, si vous en faites des vrais, il vous faudra plusieurs path_track, pour ne pas que le train tourne "d'un coup", sinon ça sera particulièrement moche et pas réaliste ;) .
On peut aussi utiliser les path_track pour faire un ascenseur sur plusieurs étages (sur un étage, une func_door suffit ^^ ), dans lequel chaque path_track est un arrêt d'étage. C'est plus complexe à gérer, mais c'est possible :) .
Cette partie n'est pas bien remplie, et pour cause, je ne vais faire que vous expliquer ce que sont les NPC. Pour apprendre à les utiliser, je vais vous envoyer lire le big-tutoriel de Tortue Facile.
NPC signifie Non-Player Character. Ce sont des entités pourvues d'une intelligence artificielle (AI) non contrôlés pas le joueur. En clair, c'est tout ce qui bouge et qui n'est pas le joueur (Gordon Freeman).
Alyx Vance est un NPC, tout comme Barney, Eli ou encore les vorts. Ce sont des NPC qui interagissent "amicalement" avec le joueur.
Les Combines, les headcrabs, les striders.. sont aussi des NPC, mais eux interagissent "méchament" avec le joueur.
Les otages de Counter Strike sont aussi des NPC :) ...
Bref, des NPC, il y en a partout (voici une liste de tous les NPC qui existent dans Half-Life², pour vous donner une idée).
C'est ici que je vais laisser là main à Tortue facile. Mes connaissances en manipulation des NPC n'est pas suffisante pour que j'écrive un cours la dessus. C'est pourquoi je vous envoie suivre le big-tuto que Tortue a écrit (bien qu'il ne soit pas fini).
Il peut être intéressant d'infliger des supplices aux joueurs. Comme c'est un peu méchant, il faut bien évidemment penser à les soigner par après, histoire de se faire pardonner ^^ .
Désintègre tout ce qui rentre en contact avec, y compris le joueur
Petits bobos
Le meilleur moyen d'infliger des blessures à un joueur est sans conteste l'utilisation d'un trigger_hurt. Quand le joueur passe/touche le trigger_hurt, il se voit infliger un certain nombre de dommages.
Les propriétés du trigger_hurt sont assez simples. Voici les principales :
Start disabled : pour que l'entité ne soit pas active par défaut
Filter name : pour utiliser un filtre, comme filter_activator_team
Damage : le nombre de points de vire retirés toutes les demi-secondes
Damage type : le type de dégâts infligés (générique, décharge électrique, toxique, brulé...). Il y a beaucoup de choix mais certains ne se différencient pas vraiment des autres.
Du côté des flags, note qu'il y a la possibilité d'infliger des dégâts aussi aux NPC, ce qui peut être intéressant. Infliger des dégâts aux objets, euh, je vous laisse y trouver une utilité :-° .
Hazardous environment
Dans Half-Life², il est courant de rencontrer des étendues toxiques, qui renforcent l'idée que les Combines exploitent les ressources de la Terre sans ménagement pour l'écosystème. On m'a demandé plusieurs fois comment reproduire cette "eau" toxique qui blesse le joueur. Rien de plus simple ! Il suffit de placer un trigger_hurt sur toute la surface de l'eau. Ainsi, quand le joueur touchera l'eau, il touchera aussi le trigger_hurt, et se blessera :
Map js_coop_thunder
Et en passant, les textures utilisées pour un milieu toxique sont :
nature/blendtoxictoxic004a pour les displacements
nature/toxicslime002a pour la surface de l'eau
Et pour donner un effet luminescent à la matière toxique, vous pouvez ajouter des light à la surface de l'eau (on le voit sur le screen) avec comme Brightness la couleur 216 183 105 70.
Kill instantané
Le trigger_physics_trap s'utilise de la même façon que le trigger_hurt, mais son action n'est pas pareille : dès que le joueur le touche, il est tué instantanément. Mais c'est plus subtil que ça ^^ . Le nom de l'entité suggère quelque chose ayant rapport avec les "objets physiques". Le trigger_physics_trap a la propriété de désintégrer tout ce qui le touche. Par exemple, si vous y lancez un objet avec le Gravity-Gun, l'objet se désintègrera (avec un petit effet). Et donc, si le joueur le touche, il est lui aussi désintégré.
Vous pouvez définir 3 types de désintégration différents, au moyen de la propriété Dissolve Type.
Les medipacks sont les trousses de soins qui redonnent de la vie au joueur. Ils peuvent être disposés un peu partout dans le niveau, tant dans HL² que dans HL²DM. Dans le cas de HL²DM, ils réapparaissent après un certain temps.
Il y a deux types de medipaks dans HL² : les petits et les gros, qui se placent respectivement avec les entités item_healthvial et item_healthkit
Du côté des batteries de rechargement de combi, il n'y en a qu'une seule sorte : item_battery.
Les chargeurs
Du côté des chargeurs, c'est plus intéressant. Ici aussi il y a des chargeurs pour régénérer la vie, et d'autres pour recharger la combi. Mais il y en a aussi un qui fait les deux, et qui charge la combi à 200%, comme ceux qu'on rencontre dans la Citadelle des Combines.
item_healthcharger permet de placer un poste de régénération de vie. Il n'y a rien de particulier avec cette entité.
item_suitcharger permet de placer un poste de rechargement pour la combi. Pour en faire un chargeur à la fois de vie et de combi, il suffit de cocher le flag Citadel recharger.
Le chargeur de dm_lockdown
Hey, dans dm_lockdown il y a aussi un chargeur qui charge à 200% de combi, mais qui ne ressemble pas à un item_suitcharger. Comment ça se fait ?
En réalité c'est aux faux. C'est juste un item_suitcharger avec un model plus complexe que l'on a ajouté par-dessus (le gros model cache le petit quoi ^^ ). Ainsi, quand le joueur s'en approche et fait "E" (touche Utiliser) pour recharger, il fait E sur l'item_suitcharger :) . C'est tout simple donc.
Des entités bloc ?
Les deux chargeurs vu précédemment sont des entités point. Du temps d'Half-Life 1, les chargeurs muraux se faisaient avec un bloc texturé transformé en entité. Et c'est toujours possible avec Half-Life², mais seulement avec Half-Life² ! Ca ne marche donc pas dans HL²DM et les autres mods.
func_healthcharger définit un chargeur de vie.
func_recharge définit un chargeur de combi.
A vous maintenant de texturer ces chargeurs comme vous le désirez ^^ .
Dans Half-Life² et la plupart des mods comme Counter-Strike (mais pas Day Of Defeat), vous pouvez poser des armes par terre. Mais je pense que vous le savez déjà ^^ .
Les armes
La pose d'armes par terre est relativement simple. Chaque arme correspond à une entité et le nom de ces entités commence toujours pas weapon_, ce qui facilite grandement le recherches. Après cette particule weapon_ se trouve le nom de l'arme. Par exemple, l'entité qui correspond à l'arbalette est weapon_crossbow (crossbow = arbalette en anglais).
Histoire de vous faciliter la vie, je vais lister toutes ces entités :)
Les item_item_crate, on en croise souvent dans HL². Ce sont ces petites boites en bois qui contiennent des munitions, des batteries pour la combi ou des medikits.
Voici les propriétés de cette entité :
Explosion Damage : Mettez ici une valeur différente de zéro si vous souhaitez que la caisse produise une explosion si elle est cassée
Explosion Radius : C?est le diamètre de l?explosion, si elle à lieu, en unités de Hammer
Item Type : C?est ce que la caisse contient. Choisissez dans la liste, l?entité qui sera contenu dans cette caisse
Item Count : C?est le nombre de fois que le type d?entité sera libéré lors du cassage de la caisse.
Les item_ammo_crate représentent les grosses caisses en acier (style armée ^^ ) quand lesquelles sont entreposées des munitions :
Vous pouvez évidemment définir le type de munitions que cette boîte va contenir. Cela ce fait via la propriété Ammo Type de l'entité. Vous n'avez qu'à choisir dans les différentes propositions de munitions le type qui vous convient.
Il n'y a pas de système spécial pour donner des armes par défaut dans une aventure solo. On utilise les même entités que celles vues précédemment. Mais on ne les place pas n'importe comment. On les met dans le joueur !
Dans le joueur ? Dans l'info_player_start alors ?
Exactement ! Regardez ce screen ; toutes les armes sont placées dans l'info_player_start. De cette manière, en apparaissant, le joueur les prendra directement comme si de rien n'était :) .
Il ne faut pas non plus oublier de fournir la combinaison. La combi se place avec l'entité item_suit, de la même façon qu'une arme, ce qui veut dire que si vous voulez la donner par défaut, vous devez le mettre dans l'info_player_start, comme ceci :
Bien évidemment, vous pouvez la mettre dans un autre endroit, pour que le joueur puisse l'enfiler, comme au début d'HL² :) .
Vous pouvez choisir de donner des armes aux joueurs, dès leur respawn. Cela se fait avec l'entité point game_player_equip.
Insérez donc une entité game_player_equip. Ouvrez les propriétés. Comme vous le voyez, la liste des propriétés est assez peu fournie. Pour ajouter des armes et items, ce n'est pas vraiment compliqué, mais ça nécessite de passer en mode d'édition normale. Dans le panneau des propriétés, cliquez sur SmartEdit, pour passer en mode d'édition normale.
Pour ajouter une arme ou un item (comme un item de batterie de combi) à donner au joueur, cliquez sur le bouton Add. Dans la boîte de dialogue qui s'ouvre, tapez le nom de l'arme/item dans le champ Key, et le nombre de fois qu'il sera donné dans le champ Value. Mettez 1 dans le champ Value s'il s'agit d'une arme. Si vous souhaitez donner des munitions en plus, vous devez insérer une nouvelle clé, avec un item de munition.
Par exemple, je vais donner un shotgun. Mettez dans le champ Key, le nom de l'entité de l'arme désirée, c'est à dire, pour notre exemple, weapon_shotgun :
Puis validez :
Voilà. Le joueur aura un beau gros shotgun dès son respawn. Nous allons maintenant donner des munitions en plus. Car vous aurez remarqué que dans Value, j'ai indiqué 1. Cela ne sert à rien de donner 2 fois le gun par exemple. Ce n'est plus comme au temps de CS1.6 ou on donnait 3 P90 pour avoir 2 recharges de P90 en plus :lol:
Donc, insérez une nouvelle clé, avec comme paramètre le nom de l'item de munition de shotgun, c'est à dire item_box_buckshot . Mettez 2 comme Value. Comme ceci :
Validez :
Temps que nous y sommes, ajoutons aussi des munitions pour le SMG :
Ce qui donne :
Vous pouvez aussi ajouter des item_battery, pour recharger la combinaison du joueur. 1 item_battery vaut 30. Donc, si vous voulez recharger complètement la combi, mettez 3 dans le champ Value ;) (si on met 4, cela dépasse de 100, et alors, aucune batterie n'est ajoutée. Je sais, c'est con :lol: ) :
Nous allons maintenant voir comment on peut enlever (ou supprimer) les armes qu?un joueur possède, au moyen de l'entité trigger_weapon_strip.
trigger_weapon_strip s'utilise exactement comme un trigger_multiple. Quand le joueur passera dans la zone du Trigger, il "droppera" toutes ses armes.
Comme il drop ses armes, elles se retrouvent par terre ! Il peut alors les ramasser en appuyant sur la touche Action (E). Ce n?est pas l?idéal. Pour résoudre ce problème, ouvrez les propriétés du trigger_weapon_strip. Mettez la propriété Kill Weapons en position Yes.
Il est à noter que ce joueur se retrouvera sans armes, c'est embêtant. Voila pourquoi il peut être bon de donner au moins une arme, après le passage dans le trigger.
Vous avez peut-être déjà croisé des maps nommées js_coop_quelqueChose ou coop_quelqueChose. La particule js vient des initiales du mappeur qui a créé la première map coopérative : Joe Scoma. Ces maps coopératives se jouent en Team-DM, mais avec une seule team (Rebel ou Combine). Les joueurs doivent terminer ensemble la map, qui peut être soit un puzzle soit une aventure. Dans le cas du puzzle, les joueurs doivent ruser pour réaliser des épreuves. Il n'y pas généralement pas de NPC. En revanche, dans les aventures, les joueurs affrontent des NPC, et c'est de ce mode de jeu que je vais vous parler...
Si vous voulez vous lancer dans le mapping HL² Coopératif, vous pouvez vous tourner vers le mod Synergy, disponible sur Steam. C'est plus abouti que HL²DM.
Dans les maps coopératives, il n'y a généralement qu'une seule équipe.
Une seule équipe signifie donc qu'une seule des deux équipes est autorisée et l'autre bannie. Malheureusement, HL²DM ne permet pas de ne jouer qu'avec une seule équipe. Il va donc falloir se débrouiller, via un jeu d'entités pour empêcher une des deux teams de respawmer, et de faire changer les joueurs d'équipe s'ils se trouvent dans la mauvaise.
Changer un joueur d'équipe
Changer un joueur d'équipe se fait par le biais d'une commande. Cette commande, qui se nomme cl_playermodel, doit être envoyée à une entité point_clientcommand. Si on veut qu'un Combine devienne un Rebel, il faut que le Combine passe dans un trigger_multiple. Dès qu'il le touche, le trigger envoie la commande au point_clientcommand (nommé clientCommand) pour dire de changer le model du joueur. Donc ici, on va demander de changer pour un model de rebel.
Pour séparer les deux équipes, il suffit d'utiliser les entités info_player_rebel et info_player_combine. Les rebels sont autorisés, donc ils peuvent apparaitre dans la salle de respawn. Quand aux combines, ils ne peuvent pas se joindre aux rebels. Donc on va placer les info_player_combine dans une salle, qui contiendra le fameux trigger_multiple pour changer le joueur d'équipe. Il y aura aussi un trigger_physics_trap, pour tuer les joueurs.
Voici le schéma de ma salle de respawn :
La grande pièce est réservée aux rebels et la plus petite aux combines. J'ai donc placé les points de respawn des combines les pieds dans le trigger_physics_trap, et le bassin dans le trigger_multiple qui se chargera d'appeler le point_clientcommand, comme ceci :
Il n'y a rien de spécial à modifier pour le trigger_physics_trap. Pour le trigger_multiple, il suffit juste de lui définir l'output pour envoyer la commande que clientCommand.
HL²DM n'est pas prévu pour utiliser des NPC, ce qui pose pas mal de différences avec les NPC dans HL², solo.
Les NPC buggés
Certains NPC ne fonctionnent pas sous HL²DM. Généralement, quand vous en mettez un et qu'il ne fonctionne pas (après lui avoir défini une relation, (voir plus bas)), c'est qu'il n'est pas géré. La plupart des NPC courants sont évidemment générés, à l'exception des zombies.
Les zombies
Si vous mettez des zombies et que vous testez votre map, le jeu va planter. Les zombies ne fonctionnent que si la map est jouée sur un serveur tournant sous Linux. C'est con mais c'est comme ça. Si vous décidez de faire une map avec des zombies, il vous faudra obligatoirement un serveur Linux (que vous faites vous-même, ou bien un serveur dédié Linux). Si vous utilisez le Dedicated Serveur proposé via Steam, c'est un serveur Windows, pour comme tester sa ma en local directement avec HL²DM. C'est la raison pour laquelle il y a si peu de maps coop avec des zombies, c'est tout simplement casse pied pour tester.
L'amitié monstres - joueurs
Sous HL²DM, tous les NPC sont neutres. Comprenez, ceux qui sont normalement méchants n'attaquent pas le joueur. Il faut donc, pour chaque type de NPC, utiliser une entité ai_relationship pour définir le comportement du NPC vis-à-vis du joueur.
Prenons l'exemple du headcrab. L'entité qui permet d'insérer un headcrab est npc_headcrab. Créez une entité point ai_relationship et définissez ses propriétés comme ceci :
Name : ai_headcrab
Subjects : npc_headcrab
Targets : !player
Disposition : Hate
Start Active : No
Reciprocal : Yes
Je définis donc que les npc_headcab ne doivent pas aimer le joueur (!player) et que c'est réciproque. La relation n'est pas active par défaut. Il est conseillé de l'appliquer au chargement de la map. Pour cela, rien de plus simple, un logic_auto :
Output named
Targets entities
Via this input
Parameter
Delay
OnMapSpawn
ai_headcrab
ApplyRelationship
<none>
0.00
A vous de créer les autres ai_relationship, pour les autres NPC :) .
Faire apparaitre les NPC
Il est grandement conseillé de toujours utiliser un npc_template_maker pour faire apparaitre les NPC. Un npc_template_maker est une entité qui fait apparaitre un NPC et qui a surtout la capacité d'en faire apparaitre plusieurs à la suite ou en même temps.
Faisons un exemple avec un headcrab. Créez une entité npc_headcrab, et donnez-lui comme nom template_headcrab. Ce ncp_headcrab servira de base. C'est lui que les npc_template_maker feront apparaitre.
L'entité npc_headcrab ne demande pas de configuration spécifique, hormis au niveau des flags. Comme on va utiliser l'entité par le biais d'un npc_template_maker, il va falloir l'indiquer. Pour cela, cochez le flag Template NPC.
Le npc_template_maker est assez simple à utiliser aussi. Il suffit de lui indiquer le NPC à faire apparaitre, combien de fois, et combien il peut y en avoir en vie en même temps :
Num. of NPCs : le nombre de NPC total qui seront spawnés
Frequency : la fréquence d'apparition, en secondes
Max Live NPCs : le nombre de NPC en vie en même temps. Si vous laissez 1, le npc_template_maker attendra que celui qui vit soit tué avant de faire apparaitre le second
Name of template NPC : le nom du NPC. Dans l'exemple, c'est template_headcrab
Le npc_template_maker doit être désactivé par défaut (Start active : No). Vous devez donc lui donner un nom pour l'appeler et ainsi l'activer. L'activation se fait via l'input Enable. Ca permet aussi de ne faire apparaitre que les NPC que les joueurs vont voir. Inutile donc de faire apparaitre au chargement de la map l'antlion guard que les joueurs ne verront qu'à la fin du niveau.
Output named
Targets entities
Via this input
Parameter
Delay
OnQuelqueChose
maker_headcracb_1
Enable
<none>
0.00
L'entité possède aussi un flags Infinite children. Il permet de faire apparaitre un NPC une infinité de fois (jusqu'à ce que le npc_template_maker soit désactivé, avec l'input Disable). Ce flag ne marche pas bien avec les npc_manhack. Et de manière générale, on ne sait pas faire apparaitre plus d'une quinzaine de manhacks par npc_template_maker.
Eh oui, le NPC que fait apparaitre ne npc_template_maker apparait à sa place donc il ne doit pas toucher le seul pour éviter que le NPC ne se retrouve coincé.
Voici par exemple un "champ" de respawn pour headcrabs en folie (dans ma map js_copp_thunder) ^^ :
Paramétrer les NPC
Comme je l'ai déjà dit, les NPC dans HL²DM c'est pas toujours ça. Et pour cause, tirez une fois sur un monstre, hop, il est mort. En fait, il va falloir définir "à la main" la vie de chaque type de NPC, et les dommages qu'il provoque avec ses attaques.
Pour définir ces variables (ce sont des variables dédiées, pouvant être tapées dans la console en fait), on va se servir d'une entité point_servercommand. Placez donc cette entité point, et donnez-lui comme nom serveur.
Lors du chargement de la map, il va falloir définir ces variables. Pour cela, il suffit de faire un output vers l'entité point_servercommand qui appliquera la variable. Je vous conseille de créer un logic_relay qui ne contiendra que les outputs vers le point_servercommand. Ce logic_relay sera appelé au chargement de la map, avec le logic_auto que nous avons créé pour établir les relations NCP - Joueurs.
Les outputs du logic_relay sont de ce type :
Output named
Targets entities
Via this input
Parameter
Delay
OnTrigger
serveur
Command
sk_headcrab_health 50
0.00
OnTrigger
serveur
Command
sk_headcrab_fast_health 50
0.00
OnTrigger
serveur
Command
sk_headcrab_poison_health 50
0.00
Ces variables sk sont différentes pour chaque type de NPC. Vous pouvez consulter le wiki de Valve. Pour chaque entité, ces variables sont mentionnées :) .
Faites simple !!! Evitez les séquences de NPC avec par exemple des antlions qui respawnent quand le joueur marche sur le sable (ça ne marche pas), des antlions qui volent d'un point à un autre (avec ça, crash du serveur Linux garanti (bizarrement, ça marche sous Windows, le contraire des zombies quoi ^^ ))...
Contentez-vous d'utiliser un path_corner pour indiquer la destination des NPC, ne vous compliquez pas la vie ;) .
Dans les maps coop, les armes sont toujours posées par terre. C'est idiot, il suffirait d'utiliser un game_player_equip. Et bien non ! Le game_player_equip, au-delà de 7 - 8 joueurs provoque des problèmes de connexion et d'apparition des joueurs. Ce n'est pas systématique mais ça peut arriver. Son utilisation est donc déconseillée.
Le Gravity Gun
Si vous faites une map coop avec des NPC (donc pas une map de type puzzle), ne donnez jamais le Gravity Gun. Le fait de tirer certains objets à la tronche des NPC (comme les antlions) peut provoquer un crash du serveur. A éviter donc.
Comme le Gravity Gun est donné par défaut, il faut donc l'enlever avec un trigger_weapon_strip.
Fin de la map
L'entité point game_end permet de mettre fin à la map en cour. La map suivant est alors chargée. C'est le seul moyen pour changer de map quand le niveau est terminé.
Donnez un nom à votre game_end, et appelez-le au moment opportun avec l'input EndGame.
Empêcher le blocage des joueurs
Les passages
Évitez de faire trop de passages exigus dans lesquels les joueurs pourraient se bloquer. Par bloquer j'entends deux joueurs qui tentent de passer une porte en même temps... Pour éviter ça, je conseille de mettre un petit trigger_push pour les pousser et éventuellement pousser un joueur qui s'amuserait à bloquer le passage (il n'y a rien de plus embêtant que ça), en particulier dans les portes et les conduits de ventilation.
Les téléporteurs
Entrer dans un téléporteur à plusieurs ne pose pas de problème. Par contre, ça peut coincer à la sortie ! Là aussi, mettez un trigger_push qui englobe les sorties de téléporteurs pour poussez les joueurs et les empêcher des se bloquer les uns dans les autres.
Une autre technique est de désactiver le téléporteur pendant une seconde à chaque fois qu'un joueur le touche. Ça peut être un bon moyen si le trigger_push ne règle pas bien le problème.
Ce sont des repères à placer sur le sol pour indiquer aux otages qu'ils peuvent marcher à ces endroits (et aux alentours). Ces entités ne sont plus utilisées. Il faut utiliser le système Mesh utilisé par les bots
Les otages
Pour placer un otage, on utilise l'entité point hostage_entity. Ça se place exactement comme un info_player_machintruc. Veillez à ce que votre otage n'ait pas de contact avec le sol ;) .
(de gauche à droite, les styles A, B, C et enfin D)
Zone de récupération
Une zone de récupération se place avec l'entité bloc func_hostage_rescue. Il vous suffit juste de créer un bloc qui s'étend sur toute la zone où les CTs peuvent évacuer les otages. Transformez ce bloc en func_hostage_rescue, comme ceci :
Pour indiquer au jeu que la map jouée est une map de type defuse, il suffit de placer l'entité qui définit la zone où les terroristes peuvent poser le petit paquet de C4. Cette entité est func_bomb_target.
Pour la placer, il vous suffit de créer un bloc avec la texture toolstrigger sur toute la zone où la pose de la bombe sera autorisée, et ensuite, il ne vous reste plus qu'à convertit ce bloc en func_bomb_target, comme ceci :
Le point de pose A de de_dust2
C'est tout ? Et quand la bombe explosera, tout ce qui est autour explosera aussi ?
Ehhh non. Il faut le faire exploser vous même !
L'entité func_bomb_taget possède un output appelé BombExplode, et qui se déclenche dès que la bombe explose.
Pour simuler des explosions, il vous suffit d'ajouter des entités env_explosion qui seront appelées par cet output. Vous pouvez aussi ajouter quelques env_fire ou un ambient_generic et autres fioritures, mais c'est moins important que les env_explosion. Pensez aussi à placer les env_explosion près d'objets qui sont censés exploser, comme des caisses (dans le cas de de_dust), comme ceci :
Il n'y a pas grand chose à dire sur les maps funs (aim_, fy_, fun_, awp_...). Ces maps sont normalement des maps d'entraînement créées pour les teams. Ce sont des maps à l'architecture simpliste (trop simpliste), avec des armes posées par terre, ou données lors du respawn.
Les mappeurs commencent généralement par une map de ce type, histoire de prendre Hammer en main. Normalement, cette première map ne devrait pas être publiée et diffusée. C'est une map créée pour votre apprentissage du mapping, ce qui veut dire qu'elle n'est pas au point, et c'est en faisant de vraies maps comme les de_ ou les cs_ que vous évoluerez dans le mapping.
Je vous expliquerai dans la partie d'après comment poser des armes par terre ou les donner au respawn ;) .
Pour créer une zone d'achat dans Counter-Strike Source, c'est relativement simple : il suffit de créer un bloc, avec la texture toolstrigger, qui recouvre l'entièreté de la zone dans laquelle les joueurs pourront acheter leurs armes et leur équipement. Ensuite, il ne reste plus qu'à convertir ce bloc en func_buyzone :
Il n'y a qu'une seule propriété : l'équipe qui est autorisée à acheter dans cette zone. C'est donc la propriété Team Number. Vous laissez 0 si les deux teams peuvent acheter, sinon, spécifier laquelle y est autorisée :) .
Un étang est simplement fait d'un bloc d'eau, mais il y a un petit plus : des poissons !
Pour ajouter des petits poissons dans une étendue d'eau, il vous suffit de placer une entité point func_fish_pool au centre de cette étendue d'eau. Vous devez veiller à ce que cette entité soit complètement immergée, sinon vos poissons nageront à la surface ^^ :
Cette entité n'a que trois propriétés :
World model : c'est le model qui sera utilisé pour générer les poissons. Je vous conseille de prendre les pitits poissons de de_inferno : models/props/de_inferno/goldfish.mdl
Fish Count : c'est le nombre de poissons générés
Max Range : distance maximale à laquelle les poissons sont autorisés à aller
Bon, comme ma map était trop moche, je vous montre un screen de la fontaine d'inferno :D
Poser des armes par terre est quelque chose de très simple. Si avec CS1.6 il n'y avait qu'une entité qu'il fallait paramétrer, sous Source, il y a une entité par arme, ce qui simplifie grandement les choses.
Toutes ces entités commencent par weapon_, excepté item_defuser qui sert à placer un kit de désamorçage. Il est à noter que les armes placées par terre n'ont qu'un chargeur (celui qui est déjà dans l'arme), et il n'est pas possible d'en mettre d'autres.
Ci-dessous se trouve la liste complète des entités d'armement de Counter.
Si vous avez lu le chapitre sur les armes d'Half-Life², vous savez comment utiliser l'entité game_player_equip : elle s'utilise exactement de la même manière. Si vous n'avez pas lu ce chapitre, allez le lire, la démarche fonctionne de la même façon que pour CS ;) .
Permet de créer une zone de régénération en munitions, métal et santé
Dans les salles de réapparition de Team Fortress² se trouvent souvent des grosses armoires grises qui distribuent munitions, métal et santé : ce sont des zones de régénération :) .
Ces zones de régénération sont constituées de deux entités : l'armoire et la zone pour laquelle la régénération en munitions, métal et santé est active.
L'armoire
L'armoire n'est rien d'autre un prop_dynamic dont le model est models/props_gameplay/resupply_locker.mdl. Il ne faut pas oublier de donner un nom a l'entité, car on l'utilisera avec le func_regenerate !
Le func_regenerate
C'est l'entité qui symbolise la zone dans laquelle la régénération sera active. Cette entité possède 3 propriétés intéressantes :
Team : soit Blue (juste pour l'équipe Bleue), soit Red (juste pour l'équipe Rouge), soit Any (pour les deux équipes)
Start Disabled : ça peut toujours être utile ça
Associated Model : c'est ici qu'intervient le nom du prop_dynamic. C'est pour dire au model de s'ouvrir ou de se fermer.
Il est important de disperses par-ci par-là des recharges en munitions, métal et quelques trousses de soin. Voici les différentes entités point qui permettent de les placer :
Permet de définir un filtre d'activation en fonction de l'équipe
filter_activator_tfteam ressemble beaucoup au filter_activator_team, hormis qu'elle est faite pour Team Fortress² ^^ .
La propriété Team peut prendre trois valeurs : Blue, Red et Any. La valeur Any n'est pas vraiment utile, puisque le but de cette entité est de dissocier les deux team ^^ .
Permet d'afficher un signale "Interdit" à l'équipe adverse et l'empêche de pénétrer dans la chambre de respawn
Les chambres de respawn de TF² sont un peu spéciales. Valve semble avoir trouvé amusant que les faire quasi toutes suivant un même schéma. Il n'est bien sur pas obligatoire de suive ce schéma à la lettre et faire comme bon vous semble. Moi je vais quand même vous expliquer comment sont faites les chambres "classiques" :)
Il n'y a rien de bien compliqué dans la création d'une chambre de ce type. Il suffit simplement de mettre une porte qui laisse sortir et entrer les membres d'une équipe, mais qui empêche les membres de l'autre équipe de renter.
Les points de respawn
Les points de départ se définissent avec les entités info_player_teamspawn. Il suffit ensuite d'indiquer l'équipe pour laquelle ces points sont associés. C'est la propriété Team. Je reviendrai sur les autres propriétés, plus tard ^^ .
La porte principale
La porte principale est celle qui laisse entrer et sortir. C'est en fait un prop_dynamic parenté avec un func_door, le func_door lui-même motorisé par un trigger_multiple. En clair, rien de bien compliqué. Il convient néanmoins d'appliquer une filtre d'activation sur le trigger_multiple, pour que le porte ne s'ouvre que si c'est un membre que l'équipe qui veut passer, et non un membre de l'équipe adverse. C'est ici que va intervenir le filter_activator_tfteam vu précédemment.
Le prop_dynamique utilise le model models/props_gameplay/door_slide_large_door.mdl (le gros respawn de ctf_2fort par exemple). Ce prop est parenté au func_door, habillé de nodraw. Je vous laisse le soin de créer cela par vous même :) .
Le trigger_multiple ouvrira la porte au moment de l'output OnStartTouchAll et la fermera lors de l'output OnEndTouchAll. N'oubliez pas de spécifier l'entité filter_activator_tfteam dans sa propriété Filter Name !
La porte secondaire
C'est une porte comme il y a dans ctf_2fort, qui sépare les points de respawn de la zone de régénération. C'est une simple porte qu'on ne sait ouvrir que d'un coté. Bref, un ou plusieurs func_door et un trigger_multiple d'un seul coté. Un truc simple quoi ^^ .
Délimitation de la chambre
Il convient de donner un nom et quelques propriétés à chaque chambre de respawn. Pour cela, on englobe la totalité de la chambre dans un func_respawnroom. Il ne reste plus qu'à éditer deux petites propriétés :
Name : nom de la chambre. C'est très important, surtout pour les maps comme cp_well où les respawn changent.
Team : Blue, Red ou Any
Et pour finir...
...le func_respawnroomvisualizer. C'est cette entité qui fera apparaître un signal "Interdit", et qui empêchera que l'équipe adverse n'entre dans la chambre.
Il faut placer cette entité bloc, en nodraw, sur toute la largeur et la hauteur de la porte (la taille du func_door en fait). Ensuite il faut renseigner sa propriété Associated Respawn Room avec le nom de la chambre de respwn (func_respawnroom) pour laquelle l'entité sera effective :) . Les autres propriétés n'ont pas grand intérêt.
Oblige tous les joueurs à réapparaître. Les constructions sont aussi détruites.
Une petite entité qui peut s'avérer amusante est game_forcerespawn. Une fois déclenchée, tous les joueurs réapparaissent et les constructions des ingénieurs sont détruites. Les bombes collantes du démoman sont aussi enlevées. Les joueurs réapparaissent, mais ne sont pas tués. C'est un peut comme la Sudden death (Mort Subite).
Pour appeller l'entité, il suffit d'utiliser son input ForceRespawn. Et en bonus, vous pouvez choisir d'échanger les teams avec l'input ForceRespawnSwitchTeams.
Vous pouvez aussi utiliser l'output OnForceRespawn pour détecter l'activation de l'entité.
Cette partie est un brin plus complexe. Pour des questions pratiques, je vais vous faire de la théorie sur la gestion des rounds avant de vous parler des différents types de maps. Ça me permet de ne pas refaire les théorie de gestion pour chaque type de map, car ces théories sont applicables grosso-modo de la même façon pour les différents types de maps.
Sert à gérer les points de contrôle. Entité obligatoire pour les maps CT et TC
L'hologramme
Les points de captures sont représentés visuellement par un prop_dynamic pourvu du model models/props_gameplay/cap_point_base.mdl (3 skins disponibles) et d'une entité team_control_point que l'on place au centre du prop_dynamic.
Le team_control_point affiche un hologramme qui indique à quelle équipe le point de capture appartient. Cette entité possède quelques propriétés qu'il est utile de définir :
Name : nom de l'entité, qui servira pour l'entité qui permet de capturer le team_control_point
Print Name : le nom du team_control_point qui sera affiché à l'écran. Mettez ce que vous voulez, mais pensez à le mettre en anglais
Default Owner : l'équipe à laquelle le point de contrôle appartient au début du round. Si le point est neutre, comme le point middle de cp_well, sélectionnez l'option Neither
Index : le numéro du point de capture (ça définit l'ordre d'affichage des points de capture dans le base de l'écran).
Le trigger
Il faut maintenant créer un trigger qui couvrira la zone dans laquelle le ou les joueurs pourront capturer le team_control_point. Ce trigger se définit avec l'entité trigger_capture_area.
Propriétés
Control point : nom du team_control_point
Can RED Cap? : l'équipe RED peut-elle capturer ce point ?
Can Blue Cap? : l'équipe BLUE peut-elle capturer ce point ?
Number of RED players to cap : nombre des joueurs RED nécessaires pour capturer
Number of BLUE players to cap : nombre des joueurs BLUE nécessaires pour capturer
Red Spawn Adjust : permet d'ajuster le temps de réapparition des joueurs RED (voir explication plus bas).
Blue Spawn Adjust : permet d'ajuster le temps de réapparition des joueurs BLUE (voir explication plus bas).
Time to cap : temps, en secondes, nécessaire à la capture du point
Outputs
Remplacez le symbole * par le numéro de l'équipe (RED = 1 ; BLUE = 2).
OnStartTeam* : Quand l'équipe * commence à capturer
OnBreakTeam* : Quand la capture de l'équipe * est interrompue
OnCapTeam* : Quand l'équipe * vient de capturer
OnStartCap : Quand une équipe commence à capturer
OnBreakCap : Quand la capture d'un équipe est interrompue
OnEndCap : Quand une équipe vient de capturer
Changer le skin du model à la capture
Lorsque le point est capturé, il ne faut pas oublier de changer le skin du prop_dynamic, pour qu'il soit en rapport avec la couleur de l'hologramme. Il vous suffit d'utiliser les outputs OnCapTeam1 (RED) et OnCapTeam2 (BLUE) et de spécifier le nouveau skin :
Output named
Targets entities
Via this input
Parameter
Delay
OnCapTeam1
nomdumodel
Skin
1
0.00
OnCapTeam2
nomdumodel
Skin
2
0.00
Le team_control_point_master
Le role du team_control_point_master est difficile à expliquer. Cette entité gère les points de contrôle entre-eux, sans que vous ayez à y toucher. En clair, mettez l'entité dans votre map et n'y touchez pas, et votre map CP marchera ^^ . Je vais quand même vous en parler un peu, car elle est quand même utile pour certaines choses.
Cette entité intervient quand tous les points de contrôle sont capturés, autrement dit, quand une équipe gagne. Voici 3 propriétés utiles :
Cap Layout : permet de définir l'ordre d'affichage des points de contrôle. J'y reviens ci-dessous.
Restrict team from winning : permet d'empêcher une team de gagner. Laissez Neither par défaut, comme ça les deux teams peuvent gagner (c'est mieux ^^ )
Switch teams on map win? : mettez Yes si vous voulez que les teams s'échangent à la fin du round, comme dans cp_gravelpit.
Le Cap Layout
Le Cap Layout vous permet de définir la façon dont les carrés symbolisant les zones de captures seront affichés à l'écran des joueurs. Si vous laissez cette propriété vide, les zones seront affichées une derrière l'autre, comme dans cp_granary ou cp_well.
Vous pouvez bien entendu spécifier l'ordre que vous voulez, en indiquant les index des vos points de capture (souvenez-vous, la propriété Index des team_control_point) en utilisant cette syntaxe : index2 index1 index3. Si vous voulez obtenir un affichage sous forme de pyramide, comme dans cp_gravelpit, il vous suffit de mettre une virgule qui fera office de "retour à la ligne" : index2, index1 index3. Dans cet exemple, index2 sera sur la première ligne, et index1 et 3 seront sur la deuxième.
Permet de gérer le temps de jeu au sein d'un round
Le team_round_timer
Le team_round_timer a pour fonction de mettre sur place le temps de jeu pour chaque round. On peut donc spécifier le temps maximum à jouer, le temps de "setup" et d'autres petites choses. C'est lui aussi qui, nous le verrons plus tard, se chargera de mettre fin au round si aucune équipe n'a gagné avant que le temps n'expire.
Voici ses propriétés détaillées
Timer length : le temps de jeu
Max timer lenght : le temps de jeu maximum. On verra qu'il est possible de rajouter des secondes, ce qui a pour effet de faire augmenter le Timer length en cours de partie. Cette propriété Max timer length permet donc de fixer un temps qu'il est impossible de dépasser, pour ne pas que les parties durent 5 heures si les temps capturent et recapturent sans cesse les points de contrôle ^^ .
Start paused : activer le time au démarrage du round
Setup timer length : temps de setup avant le démarrage du round proprement dit. Si vous définissez un temps de setup, je vous conseille de mettre 45 secondes qui est une bonne valeur :) .
Reset time on round restart : rétablir les paramètres initiaux du timer si la partie redémarre. Je vous conseille de laisser No
Use countdown sound : mettez Yes si vous souhaitez entendre le décompte du temps (5 minutes left in the mission ^^ )
Show timer in the HUD : permet d'afficher ou nom le temps restant à l'écran
Inputs
Le possède plusieurs inputs qui peuvent se révéler utiles, et notamment AddTime. L'entité possède des inputs courants comme Enable et Disable.
Pause : met le timer en pause.
Resume : remettre en marche le timer (le contraire de Pause quoi ^^ )
SetTime : redéfinir le temps, en secondes. Le paramètre doit être un nombre.
AddTime : permet d'ajouter du temps. Le paramètre doit aussi être un nombre.
AddTeamTime : permet d'ajouter du temps pour une team. La syntaxe d'ajout est un peu spéciale. Le team RED porte le numéro 2 et la team BLUE le numéro 3. Si vous voulez ajouter 20 secondes à la team BLUE, vous devez mettre 3 20.
Restart : réinitialiser le timer.
ShowInHUD : afficher ou non le timer (0 pour No et 1 pour Yes).
SetMaxTime : redéfinir le temps maxumum du timer
AutoCountdown : activer ou désactiver le compte à rebours (0 pour No et 1 pour Yes)
SetSetupTime : redéfinir le temps de setup
Le temps de Setup
Dans les maps comme cp_well et cp_dustbowl, un certain nombre de secondes est octroyé à la création des bâtiments de l'ingénieur et à la mise en place des joueurs. C'est ce qu'on appelle le setup, mais je suppose que vous le saviez déjà ^^ .
Enfin bon, le temps de setup se défini avec la propriété Setup timer length du team_round_timer comme je vous l'ai expliqué plus haut. Le principe du setup est que c'est un moment de répit pendant lequel les deux teams ne peuvent pas s'affronter ; c'est pourquoi on dresse des portes pour empêcher le passage. Pour ouvrir les portes, il suffit d'utiliser l'output OnSetupFinished du team_round_timer. Bref, rien de bien compliqué là dedans :) .
Permet mettre fin à la map et de passer à la suivante
Comment savoir quand un round est fini ?
Quand le temps est écoulé, ou quand l'objectif est rempli.
Le temps est écoulé
Pour savoir quand le temps est écoulé c'est simple : le team_round_timer, possède l'output OnFinished qui est déclenché quand le temps est écoulé. Il suffit donc d'appeler une entité game_round_win quand le temps est écoulé. Cette entité game_round_win mettra fin au round en déclenchant la Sudden Death (Mort Subite) ou non. Si la Sudden Death n'est pas déclenchée, le round se fini par un Stalemate (Math Nul), dans le cas d'une map CP de base (sans défense/attaque).
Team : : laissez None (Sudden Death) si vous voulez que le round se finisse par une Mort Subite si il y a égalité.
Force map reset : : mettez Yes pour que la map soit réinitialisée pour le Sudden Death (les zones capturées ne seront pas conservées, pare exemple).
Switch teams on map win? : Echanger les équipes après la victoire
La mission est remplie
Il se peut bien évidemment qu'une des deux teams gagne le round avant la fin. Dans ce cas, la gestion de la victoire est reléguée au team_control_point_master et le game_round_win n'intervient pas. Et devinez quoi, vous n'avez rien à paramétrer... enfin, pour faire gagner. Car il est maintenant temps de compter les points !
Changer de map après N victoires
Pour changer de map après un certain nombre de victoir (par exemple, après 3 victoires), il suffit de compter le nombre de rounds gagnés ! Le comptage des rounds n'a rien de compliqué. On va tout simplement utiliser deux math_counter (un pour chaque équipe). Quand un round est gagné, il suffit d'ajouter un point à un des math_counter. Et quand un des deux math_counter atteint son maximum (voir la chapitre sur les déclencheurs), il déclenche un game_end qui va mettre fin à la partie et passer à la map suivante.
Output named
Targets entities
Via this input
Parameter
Delay
OnWonByTeam1
counter_red_win
Add
1
0.00
OnWonByTeam2
counter_blue_win
Add
1
0.00
Maintenant, on défini les outputs des math_counter, qui appelant le game_end (le l'ai nommé end_game) qui mettra fin à la partie.
Les maps de type CTF (Capture The Flag) sont les plus simples à mettre en place : deux flags et deux points de capture et le tour est joué !
Le flag
Le flag, ou plutôt the intelligence se place avec l'entité item_teamflag. Les propriétés sont très simples : il vous suffit de sélectionner l'équipe à qui appartient cette valise, au moyen de la propriété Team. Pensez aussi à laisser la propriété Game Type sur CTF.
L'entité possède 4 outputs intéressants : OnReturn, OnPickup, OnDrop et OnCapture (je pense qu'on comprend tout de suite leur fonction rien qu'en lisant leur nom ^^ ) ; et un input pas vraiment utile mais on ne sait jamais : SetTeam, qui permet de modifier l'équipe à qui appartient la valise.
La zone de capture
Le zone de capture est un bloc avec la texture toolstrigger converti en func_capturezone, et comme pour item_teamflag, spécifiez la propriété Team. La propriété Capture Point n'a pas besoin d'être modifiée, elle est de toutes façons ignorée en CTF. Elle servira pour les autres types de maps.
Les maps de type CP reposent sur le système points de capture comme je l'ai expliqué dans la partie précédente. Il y a plusieurs sous-types de CP :
cp_well, cp_granary : CP de base
cp_gravelpit : CP de défense/attaque sur un seul round
cp_dustbowl : CP de défense/attaque sur plusieurs rounds
CP de base
Une des deux teams gagne
Dans ce cas, tous les points de contrôle sont capturés, et le round suivant s'enchaîne tout seul. Votre team_control_point_master n'a donc pas besoin de configuration spécifique.
Le temps et écoulé
Aucune des teams n'a sur capturer tous les points (You're all losers). Dans ce cas, il faut appeler le game_round_win à la fin du temps, c'est à dire avec l'output OnFinished de l'entité team_round_timer. Spécifiez bien None (Sudden Death) pour la propriété Team du game_round_win, ce qui aura pour effet de déclencher la mort subite.
Comment associer les points de contrôles aux points de respawn comme dans cp_well et granary ?
En réalité c'est plutôt simple. Il vous suffit d'indiquer le nom du team_control_point dans la propriété Associated Control Point des entités info_player_teamspawn.
CP de défense/attaque sur un seul round
La team qui attaque gagne
Cela veut donc dire que l'équipe qui attaque a capturé tous les points. Nous sommes donc dans le cas d'une map CP de base, il n'y a rien de plus à faire. Ah si, faut penser à mettre la propriété Switch teams on map win du team_control_point_master sur la position Yes pour que les teams s'échangent à la fin du round.
La team qui défend gagne
A la fin du temps, si la team qui attaque n'a pas capturé tous les points, la victoire revient à la team qui défend. IL suffit donc d'appeler l'entité game_round_win à la fin du temps, c'est à dire avec l'output OnFinished de l'entité team_round_timer.
Pensez à bien spécifier la propriété Team du team_round_timer, pour définir la team qui remporte le point à la fin du temps !
Particularités supplémentaires
Vous devez spécifier un ordre de capture. Cela se fait avec les propriétés de type Previous Required Point qui se présentent comme ceci : BLUEBLUE Previous Required Point 1.
Vous devez également empêcher la team qui défend de gagner en capturant les points (logique ^^ ). Cela se fait très facilement en spécifiant le nom de la team qui défend dans la propriété Restrict team from winning du team_control_point_master.
Payload ne vous dit certainement rien. Pourtant, c'est le préfixe de la map officielle pl_goldrush. Ce type de jeu particulier mérite à lui seul son petit chapitre :) .
Une map payload est basée sur un système d'attaque-défense, comme cp_gravelpit ou cp_dustbowl. Les bleus attaquent et les rouges défendent. Ce qui change dans une map payload, c'est que les captures doivent se faire en faisant passer un charriot dessus. Dans pl_goldrush, le charriot est représenté par un caddie transportant une bombe bleue destinée à détruire la base rouge. Cela dit, le charriot est juste un prop_dynamic, donc théoriquement, n'importe quel model peut convenir.
Le contrôle des points
Nous allons avoir besoin de paramétrer le team_control_point_master, de cette manière :
Propriétés
Valeurs
Name
CP_Master
Start Disabled
No
Restrict team from winning
Red
Switch teams on map win?
Yes
Scoring Style
Add team score for each captured point
Play all rounds before changelevel
Only changelevel after all mini-rounds have been played to completion
Rate at which to give partial cap points for area captures
0.1
Ensuite, on va ajouter un team_control_point_round, à nommer comme le team_control_point_master :
Propriétés
Valeurs
Name
CP_Master
Start Disabled
No
Priority
0
Control points in this round
m
Restrict team from winning
Red
Ça, c'est fait. Maintenant, on va mapper l'environnement, histoire d'avoir une base de travail.
La création du chemin de fer se fait en deux temps :
le placement des models
les path_track
Oui, les path_track ! On va les utiliser pour indiquer au charriot (le train) quel itinéraire employer.
Itinéraire
Les rails sont à poser au moyen de prop_static. Pour rechercher les models, utilisez le filtre track dans l'explorateur de models. Il y a tout une kyrielle de models de rails que vous pouvez utiliser :) .
Pour symboliser les points de capture, vous pouvez, c'est recommandé, utiliser le model odels\props_trainyard rack_midcap.mdl. Voici ce que j'obtiens après avoir joué quelques minutes avec Hammer (c'est très basique ^^ ) :
Maintenant, placez les path_track. Si vous ne vous souvenez plus comment les placer, reportez-vous au chapitre qui leur est destiné. Notez qu'au niveau des checkpoints (points de capture), le charriot "monte" dessus, vous devez donc adapter vos path_track en conséquent. Mettez aussi un path_track au centre du checkpoint. Quand le charriot passera sur celui-là, le point sera capturé.
Au centre de chaque checkpoint, mettez un team_control_point, comme on le fait dans les maps CP, et donnez-lui un nom. Par exemple, CP_Partie1_x (x = numéro).
La capture
Pour déclencher la capture, on va utiliser l'output OnPass du path_track situé au milieu du point de capture. Lors de cet output, on déclenchera la capture (le SetOwer du team_control_point) et on empêchera le charriot de reculer, en désactivant le dernier path_track juste avant le path_track servant de point de capture. Voici mes outputs d'exemple pour mon point 1 :
Output named
Targets entities
Via this input
Parameter
Delay
OnPass
CP_Partie1_1
SetOwner
3
0.00
OnPass
CP_Partie1_1_relay
Trigger
<none>
0.00
OnPass
path_track_précédent
DisablePath
<none>
0.00
Le CP_Partie1_1_relay est tout simplement un lien vers un logic_relay qui se chargera d'ouvrir ou de fermer des barrières et faire d'autres trucs en rapport avec la capture comme ajouter du temps.
La prochaine capture
Nous allons le voir dans la sous-partie suivante, mais je vous en touche un mot maintenant. La capture des points se fait à l'aide d'un trigger_capture_area qui bouge en même temps que le charriot (il lui est parenté). Cette entité possède une propriété Control Point qui désigne le point de capture pour lequel elle est utilisée. Or ici, il n'y a qu'un trigger_capture_area. Il faut donc, dès qu'un point est capturé, définir le prochain point à capturer, au moyen de son input SetControlPoint, comme ceci :
Output named
Targets entities
Via this input
Parameter
Delay
OnPass
Bombe_CaptureArea
SetControlPoint
CP_Partie1_2
0.00
Dans mon exemple, CP_Partie1_2 est donc le deuxième point de capture.
Comme je l'ai laissé entendre dans l'introduction, le charriot est un func_tracktrain. Mais attention le func_tracktrain est invisible. Le model du charriot est parenté au func_tracktrain.
Créez un bloc texturé en toolsclip, que vous transformez en func_tracktrain. Nommez-le Bomb_Train. Ensuite, insérez un prop_dynamic en utilisant le model models/props_trainyard/bomb_cart.mdl, et parentez-le au func_tracktrain :
Le tracktrain demande un certain nombre de propriétés, et dans le cas du charriot, il va falloir en ajouter 3 manuellement.
Propriétés
Valeurs
ManualAccelSpeed
70
ManualDecelSpeed
150
ManualSpeedChanges
1
Voici les propriétés habituelles à adapter :
Propriétés
Valeurs
Name
Bombe_train
First Stop Target
CP_Partie1_1
Max Speed
90
Change Velocity
Linear blend
Distance Between the Wheels
20
Height above Track
1
Damage on Crush
99999
Move Sound
Cart.Roll
Start Sound
Cart.RollStart
Stop Sound
Cart.RollStop
Avant de commencer ce chapitre, je pensais naïvement que Valve avait faire une entité toute faite pour le charriot, avec gestion du dispenser, de la zone de capture et tout et tout. Evidemment, je me trompais :-° .
La zone dans laquelle les joueurs sont habilités à faire avancer le train est faite tout simplement d'un trigger_capture_area. Créez-le, tout autour du charriot, et parentez-le au train. Pensez à recouvrir le dessus du train aussi, comme ça si quelqu'un s'y trouve (moi, j'adore me mettre dessus ^^ ), il capturera aussi. Nommez cette entité Bombe_CaptureArea, et associez-lui le premier point de capture (CP_Partie1_1 dans mon exemple).
Pour terminer le montage du train, il faut s'occuper du dispenser. A la manière du trigger_capture_area, créez un bloc, avec la texture de trigger, et transformez-le en dispenser_touch_trigger (ça aurait été plus malin de nommer cette entité trigger_dispenser, mais bon, le codeur devait être dans un mauvais jour). Hum, bref, donnez un nom à cette entité (Bombe_dispenser par exemple), et parentez-là au train.
Quand vous vous faites soigner par le charriot, le rayon soignant sort de la cheminée du charriot. Ce "point de départ" du rayon est placé via l'entité mapobj_cart_dispenser (je maudis ce codeur avec ses noms stupides :p ). Pas besoin de nommer l'entité (mais bien de la parenter). Spécifiez juste le nom du dispenser_touch_trigger dans la propriété Custom touch Trigger, et spécifiez bien la team qui peut bénéficier du soin.
Voici ce que donne mon charriot, avec tous ses triggers autour ^^ :
La vitesse du charriot est influencée par le nombre de joueurs présents dans la zone de capture. Ok, mais comment connaitre leur nombre ? L'output OnNumCappersChanged du trigger_capture_area envoie le nombre de joueurs présents en son sein (le scout compte pour deux joueurs).
Le trigger_capture_area va donc transmettre le nombre de joueurs à un math_remap qui va s'occuper de redéfinir le nombre. C'est une nouvelle entité dont je ne vous ai pas encore parlé. A son tour, le math_remap va envoyer le nombre redéfini à un logic_case, qui lui va s'occuper de déterminer la nouvelle vitesse (entre 3 différentes) à donner au charriot.
Avant de voir le math_remap, voyons d'abord le logic_case, ce sera plus facile pour comprendre :
Propriétés
Valeurs
Explication
Name
Bombe_logicCase
Case 01
0
Il n'y a aucun joueur
Case 02
1
1 joueur est présent
Case 03
2
2 joueurs sont présents
Case 04
3
3 joueurs sont présents
Et en voici les outputs :
Output named
Targets entities
Via this input
Parameter
Delay
OnCase01
Bombe_train
SetSpeedDirAccel
0
0.00
OnCase02
Bombe_train
SetSpeedDirAccel
0.5
0.00
OnCase03
Bombe_train
SetSpeedDirAccel
0.75
0.00
OnCase04
Bombe_train
SetSpeedDirAccel
1
0.00
Comme on peut le voir, en fonction du nombre de joueurs, on fait changer la vitesse du charriot. Maintenant, supposons qu'il y ait 5 joueurs. Dans ce cas, il ne se passe rien ! C'est pour cela qu'on va avoir recours à un math_remap :) .
Le math_remap
Le math_remap est un entité qui reçoit une valeur, qui l'analyse et qui en retourne une nouvelle, ou tout simplement la même en fonction de l'analyse. Le math_remap permet de fixer deux valeurs (deux bornes) : une minimale et une maximale. le math_remap, en recevant une valeur, va la comparer aux deux bornes. Si la valeur est comprise en les deux bornes, cette valeur est renvoyée telle-quelle. Si la valeur est plus petite que la borne inférieure, une valeur définie à l'avance est renvoyée, de même que si la valeur est supérieure à la borne supérieure :
Minimum Valid Input Value : borne inférieure. Mettez 0.
Maximum Valid Input Value : borne supérieure. Mettez 3 (au plus 3 joueurs).
Output Value When Input Is Min. : valeur renvoyée si la valeur d'entrée est plus petite que la borne inférieure. Mettez 0.
Output Value When Input Is Max. : valeur renvoyée si la valeur d'entrée est plus petite que la borne supérieure. Mettez 3.
En mettant 3 dans Output Value When Input Is Max, ça signifie que si la valeur d'entrée est 5, la valeur de sorte sera 3 :) .
Ce chapitre, le premier des chapitres sur Portal, est principalement basé sur le level design (mapping, sans parler des entités) et explique comment s'y retrouver et débuter dans la création d'une chambre de test. Il n'y a rien de très compliqué là-dedans, mais il y a quelques astuces à connaître.
L'architecture d'une salle de test est quelque chose de basique. Les salles de Portal sont généralement très géométriques (cubes, parallélépipèdes...). Les dimensions doivent toujours être multiples de 2 car les textures du jeu sont elles-mêmes en multiples de deux.
Bon, cela étant dit, on peut commencer à mapper une petite salle de test.
Quelques infos sur les textures
Par défaut, les textures de Portal sont définies pour accepter ou non la création d'un portail. Ainsi, les textures de métal ou de vitre empêchent la création de portails. Ce n'est pas le cas pour la grande majorité des textures de murs.
Pour rechercher des textures, je vous recommande d'utiliser le filtre modular pour ce qui est des textures de murs en béton et metalwall04 pour les plaques de métal. Mettez aussi portal comme mot clé (le champ keyword) pour ne prendre que les textures de Portal.
Les bordures lumineuses
Je pense que vous l'avez remarqué, dans les différentes salles, il y a des bordures lumineuses autour des bords du plafond ou du sol :
Ce genre de bordure se fait en rétrécissant de 4 unités le plafond, tout en le gardant au centre :
La salle se retrouve donc ouverte. Pour la fermer, on crée 4 blocs à placer par-dessus. Ces blocs sont à texturer avec la texture lights/light_recessedcool002 :
Le petit bloc avec la texture lumineuse est sélectionné
Cette texture fera office de source lumineuse. On va maintenant utiliser un overlay pour simuler la propagation de la lumière sur les murs. La texture à utiliser est overlay_light_gradient, avec un V start de 0.99. Placez un overlay, que vous redimensionnez en largeur, dans le haut de chaque mur :
Et voilà, en compilant, vous devriez obtenir un résultat comme dans le jeu :) .
Les puits de lumière
Dans certaines salles, des "trous" (ou des puits) sont percés dans les plafonds ou dans les murs, diffusant une lumière très blanche. Ces "trous" font office d'entrée de lumière, puisqu'il n'y a quasi jamais de lampes dans les salles de test. Exemple de puits de lumière :
En réalité, c'est assez simple de faire ce genre de chose. Tout ce que vous avez à faire, c'est trouer votre mur, ajouter 4 blocs pour créer un "renfoncement" et un bloc pour fermer, avec une texture blanche (lights/white007 pour être précis ^^ ) :
Pour plus de réalisme, vous pouvez ajouter une lueur - un env_lightglow - dans votre puits. L'env_lightglow est à configurer comme ceci :
Les salles, ou chambres, d'observation sont les pièces cachées derrière des vitres dépolies :
Ces salles ont deux rôles principaux. Realm Lovejoy les explique, si vous passez Portal en mode Commentaires :
Citation : Realm Lovejoy à propos des salles d'observation
Ces salles d'observation en verre dépoli donnent l'impression au joueur qu'il est sous surveillance tout en permettant de garder le mystère quant à l'identité de ceux qui le surveillent. Par ailleurs, ces pièces revêtent une réelle utilité : on les utilise souvent comme sources de lumière logiques pour les salles de test.
En effet, comme il n'y a pas de fenêtres ni de lampes, les salles d'observation font office de source lumineuse (car de la lumière qui vient de nulle part, ça ne le fait pas trop ^^ ).
Le trou pour la fenêtre fait généralement 128 unités (taille standard d'un mur d'un étage en fait). Comme le montre mon screen, on voit une sorte de gros plafonnier qui diffuse de la lumière. C'est un tube de lumière, qui fait 64 unités de haut. Si vous voulez en placer un, ce qui est recommandé, vous devez donc faire une salle de 172 unité de haut (128 + 64).
Voici les textures à utiliser pour texturer l'intérieur de la salle (n'oubliez pas, du nodraw, sur les faces que le joueur ne peut voir) :
observationwall_001b pour les murs de 128 unités
observationwall_001a pour les murs de 64 unités
observation_tilefloor001a pour le sol
observationwall_001a pour le plafond
Le tube de lumière
La salle est texturée, occupons-nous du tube de lumière.
On pourrait penser que c'est un model, mais il n'est est rien. Il va donc falloir tout créer avec des blocs, et principalement avec une arche.
Pour une question de facilité, on créera un quart de cercle que l'on dupliquera par la suite pour former un cercle complet. Prenez l'outil Arch et tracez un carré de 80*80*46 (largeur * profondeur * hauteur), et créez l'arche avec ces paramètres :
Vous obtenez donc un quart de cercle. Il faut ensuite le modifier avec le Vertex Tool pour le faire tenir dans un carré :
->
Créez des copies de ce quart, pour former le cercle complet. Pensez à mettre des blocs de nodraw pour encadrer ce cylindre, pour pouvoir le convertir en func_detail. Pour les textures, voici ce qu'il faut utiliser :
plastic_light002c pour le tube
plastic_light002a pour le cadre du tube
plasticwall002a pour les partie visible du tour du cadre
white009 pour le fond du tube
Cochez les cases Treat as one et Top pour appliquer rapidement les textures dans le cylindre. Treat as one et Center pour le cadre (le bord du cylindre) :
La vitre dépolie
Il faut commencer par faire un encadrement. La référence est de prendre une largeur de 4 unités pour les "barres". Les montants d'encadrement (à l'extérieur, pas les barreaux) sont plus profonds, ils font la même profondeur que le mur. Vous devez utiliser la texture plasticwall004a.
L'armature en place, il ne reste plus qu'à faire la vitre. Faites plusieurs vitres, une entre chaque barreau. Comme pour toutes les vitres, mettez du nodraw partout, sauf sur la face que le joueur verra. Sur cette face, appliquez la texture glasswindows_refract01. La texture apparait en rose et noir, ce n'est pas grave, ça marchera ^^ :
Luminosité
Au centre de la pièce, placez une light paramétrée de la sorte :
Brightness : 183 204 218 200
BrightnessHDR : 183 204 218 150
Constant : 200000
Placez un env_cubemap au centre de la pièce, et pour terminer, mettez un light_spot, qui pointe vers la salle de test. Vous pouvez l'orienter au centre ou vers une partie de la pièce à mettre en valeur. C'est principalement ce spot qui va influencer sur la lumière que diffuse la chambre d'observation. Voici les propriétés à modifier :
Portal est une succession de salles. On pourrait dire que Portal est quasiment un long couloir avec des salles et des ascenseurs pour passer d'un étage à l'autre. Cela veut donc dire qu'optimiser un niveau est plutôt simple (hum, comprenez "plus simple que pour une aventure solo d'Half-Life² dans un environnement ouvert" :p ).
Les deux techniques principales sont les hintbrush, et les areaportals (ou les occluders). De par l'architecture carrée des pièces, c'est plutôt facile à utiliser.
Rien d'autre à dire ici, c'était surtout un petit rappel :) .
Dans Portal, la majorité des surfaces sont découpées en petits blocs, ce qui permet de les manier très facilement et d'appliquer des textures différentes d'un bloc à l'autre (des textures avec juste quelques changements). Il est ainsi possible de créer une surface composée de plusieurs textures différentes :
Ça ne se remarque pas toujours, mais si vous observez attentivement les murs de métal, vous remarquez que certains "carrés" ressortent. Ces murs sont aussi découpés et des parties ressortent plus que d'autres.
Pensez aussi à décorer les murs avec des overlays (il n'y a pas beaucoup de decals), à faire des pièces cachées, enfin bref, essayez de coller à l'ambiance de Portal :) .
C'est la seule arme de Portal : le PortalGun (Handheld Portal Device)
Voici donc l'arme principe (et la seule) de Portal, le PortalGun. C'est cette arme qui permet à Chell (l'héroïne du jeu) de créer des portails partout où elle le désire (enfin, presque partout, nous y reviendrons :) ).
Le Handheld Portal Device
Pour commencer, voici les propriétés, inputs... de l'entité. Nous verrons ensuite comment mettre en place un socle pour le poser dessus, et le proposer au joueur d'une façon digne de ce nom.
Propriétés
Il n'y a que deux propriétés intéressantes, les autres sont connues :
Can Fire Portal 1 : Laissez Yes si le Gun est autorisé à créer de portails bleus
Can Fire Portal 2 : Pareil que Can Fire Portal 1, sauf qu'il s'agit ici du portail orange
Inputs
ChargePortal1 : Charge le tir du portail bleu
ChargePortal2 : Charge le tir du portail orange
FirePortal1 : Tire le portail bleu, et si la surface le permet, ouvre un portail bleu
FirePortal2 : Tire le portail orange, et si la surface le permet, ouvre un portail orange
FirePortalDirection1 : Le sens dans lequel sera tiré le portail bleu (angle)
FirePortalDirection2 : Le sens dans lequel sera tiré le portail orange (angle)
Les outputs sont des outputs génériques, communs à ma majorité des armes d'Half-Life² ;) .
Le socle
Le socle du PortalGun est en réalité un simple prop_dynamic pourvu du model models/props/pedestal_center_reference.mdl. Donnez un nom à votre prop, par exemple pied_portalgun. Le model est par défaut en position Close (fermé). Le truc est que quand le joueur approche du socle, il se déplie et présente le PortalGun au joueur. Mais auparavant, placez le weapon_portalgun et parentez-le au prop_dynamic.
Créez maintenant un trigger_once autour du socle. C'est ce trigger qui déclenchera l'ouverture du socle. Définissez lui cet output :
Output named
Targets entities
Via this input
Parameter
Delay
OnStartTouch
pied_portalgun
SetAnimation
Open
0.00
Et voilà, le tour est joué. Quand le joueur approchera du socle et déclenchera le trigger, le bras du socle de dépliera et lui présentera le gun :) .
Les portails (orange et bleu) peuvent être ouverts de multiples manières :
par le joueur, sur des mur prévus à cet effet
par l'entité prop_portal, qui permet d'ouvrir, où le mappeur le veut, un portail (orange ou bleu)
par le PortalGun, grâce aux inputs FirePortal1 et 2.
Nous allons ici voir comment marche le prop_portal.
Cette entité comporte les propriétés habituelles ainsi que les suivantes :
Start Activated : Démarre avec le portail ouvert ou fermé
Portal Number : Type du portail : Portal 1 = bleu; Portal 2 = orange
Portal pair ID that it belongs to : ID de la paire de portail à connecter. Par défaut, cette propriété vaut 0, qui représente l'ID du PortalGun.
Un nouvel output viens faire son apparition : OnPlacedSuccessfully qui est activé si le portail s'est bien ouvert. Pour les inputs, il n'y a que deux nouveaux venus :
Fizzle : permet de fermer de portail
SetActivatedState : permet d'activer ou de désactiver le portail. Mettez 1 pour l'activer, et 0 pour le désactiver.
Vous avez dû remarquer que dans Portal, il n'était pas possible de tirer des portails sur toutes les surfaces. Je vais ici vous expliquer comment réaliser ces murs "anti-portails".
Les mur anti-portails sont très simples à réaliser. Il faut soit une texture de métal issue de Portal (la map fournie comme exemple dans le SDK en comporte quelques-unes) ou une texture de vitre. Ces deux types de textures bloquent toutes créations de portails avec le PortalGun, mais elles sont sans effets sur les prop_portal.
On peut aussi bloquer les portails avec une entité-bloc, le func_noportal_volume. Pour mettre en place cette entité, il suffit de la placer devant le mur que vous voulez protéger. Vous pouvez utiliser la texture toolstrigger.
Il y a deux types de tourelles dans Portal : les tourelles de base, qui mitraillent le joueur en poussant des cris aigus, et les tourelles lanceuses de roquettes, comme celle qui permet de détruire GLaDOS (le robot à la voie sulfureuse ^^ ) à la fin du jeu.
Tourelles mitrailleuses
Ce premier type de tourelle se place avec l'entité npc_portal_turret_floor. Il n'y a qu'une propriété, Damage pushes player, qui si elle est définir sur Yes, provoquera le recul du joueur si celui si est blessé par la tourelle.
Il y a aussi quelques flags qui peuvent se révéler utiles, comme Autostart pour démarrer automatiquement ou Out of Ammo qui autorise à tourelle à être à court de munitions (mais ne le cochez pas, sinon c'est trop facile ^^ ).
Tourelles lance-roquettes
La tourelle lance-roquettes se place via l'entité npc_rocket_turret. La pose est extrêmement simple ; d'ailleurs, il n'y a pas de propriétés intéressantes, juste un flag, Disabled, qui permet de désactiver la tourelle par défaut. Si vous le cochez, il vous faudra "réveiller" la tourelle avec son input Enable :) .
Trigger qui détecte la création d'un portail sur sa surface
Les caméras de surveillance se placent avec l'entité npc_security_camera. Il n'y a rien d'autre à dire ^^ hormis le fait de ne pas oublier de cocher le flag Autostart.
La caméra sera détachable ?
Bien sûr que non ! Et je vais d'ailleurs vous expliquer comment rendre votre caméra détachable :) .
La caméra, par défaut est fixe. Il y a moyen de la faire réagir à la physique (donc de la faire tomber ^^ ) en déclenchant son input Ragdoll, quand un portail est créé derrière la caméra.
Mais, comment détecter la création d'un portail ?
Facile, il suffit de placer un bloc, transformé en func_portal_detector à l'endroit où la création d'un portail fera tomber la caméra. Il vous suffit d'ajouter l'output OnStartTouchBothLinkedPortals au func_portal_detector. Cet output appellera la caméra avec son input Ragdoll, comme ceci :
Les fichiers avec lesquels Hammer travaille sont des fichiers au format .vmf. Comme vous le savez certainement, les maps sur lesquelles on joue portent l'extension .bsp.
La compilation est le processus par lequel on va passer d'un fichier .vmf à un fichier .bsp. En d'autres termes, la compilation sert à transformer votre fichier Hammer en une map jouable :) .
Compiler sa map n'est pas quelque chose de très compliqué car c'est Hammer, ou plutôt les compilateurs, qui vont travailler.
Comment ça les compilateurs, il y en a plusieurs ?
Oui, ils sont au nombre de 3. Chaque compilateur a une fonction bien définie et est nécessaire. Les compilateurs sont 3 petits programmes qui s'exécutent en console. Mais rassurez-vous, tout se fera seul, vous n'aurez pas besoin d'intervenir ;) .
Une compilation normale se déroule en 3 phases :
Le fichier .vmf est confié au compilateur vbsp.exe. Ce compilateur, VBSP, s'occupe de découper votre map en polygones triangulaires et de positionner les entités. Bref, c'est lui qui s'occupe de recréer l'architecture de votre map. C'est assez rapide. Dès que c'est fini, VBSP passe la main à VVIS.
Le compilateur vvis.exe prend alors le relais. VVIS va se charger déterminer la visibilité. Il va calculer pour savoir quels polygones seront visibles par le joueur, en fonction de sa position. Suivant la grandeur de votre map, VVIS peut travailler de 2 minutes à parfois 1 heure.
Dès que le calcul de la visibilité est fini, c'est vrad.exe qui se met au travail. VRAD va évaluer la luminosité de votre map. C'est lui qui va définir les ombres et les faces illuminées par vos lumières. Le temps de compilation de VRAD peut aussi être assez long.
Si vous compilez votre map simplement pour tester votre architecture par exemple, vous n'avez pas besoin de compiler avec VVIS et VRAD. VBSP suffira, mais votre luminosité sera comme dans Hammer. En revanche, si vous effectuez une compilation avant de mettre votre map en ligne, vous devez passer par les 3 compilateurs.
Maintenant que vous avez bouffé la théorie, vous allez digérer en compilant :) .
Pour compiler avec Hammer, c'est assez simple. Il vous suffit d'aller dans le menu Files puis de cliquer sur Run Map, ou de passer par la touche F9.
Une fenêtre comme celle-là s'ouvre :
C'est le mode de compilation basique. Il vous suffit de cocher les différentes options des compilateurs. Comme vous le voyez, VVIS et VRAD possèdent une option de compilation rapide (Fast). C'est très pratique quand il s'agit de tests. Comme je vous l'ai expliqué plus haut, il n'est pas obligatoire d'exécuter VVIS et VRAD pour tester sa map. Dans ce cas, il vous suffira de cocher No.
Je vous conseille fortement de cocher Don't run the game after compiling. Si vous ne cochez pas, le jeu sera lancé avec la map, et 9 fois sur 10, ça plantera ^^ .
Additional game parameters vous permet de spécifier une ou plusieurs commandes. Pour l'instant, laissez le champ vide (on ne le remplira pas souvent de toutes façons ^^ ).
Dès que vous avez bien tout paramétré, cliquez sur OK.
A ce moment, une fenêtre s'ouvre vous présentant l'évolution de la compilation :
Ce qui va défiler dans cette fenêtre sont les opérations effectuées par les compilateurs. Tout ce texte est ce que l'on appelle le log de compilation (on dit log pour aller plus vite). Le contenu de ce log se trouve dans un fichier appelé nom_de_votre_map.log.
Ainsi, si vous fermez Hammer, vous pouvez toujours accéder au log, car en cas de problème, il faudra aller le rechercher pour y trouver les erreurs. Il se trouve dans le même répertoire que votre fichier nom_de_votre_map.vmf, et vous pouvez l'ouvrir avec le Bloc-notes, comme un simple fichier .txt.
Hammer aura placé tout seul une copie de la map compilée (le .bsp) dans le dossier contenant les maps de votre mod préféré.
Pour tester la map, démarrez votre mod comme si vous alliez y jouer. Dans le menu, cliquez sur Create server (Créer un serveur).
Sous l'onglet Server, sélectionnez votre map (ici c'est la map pour le mini-tuto sur l'eau ^^ ).
Ensuite, passez sous l'onglet Game, et configurez comme vous le voulez. Par défaut, le serveur que vous allez créer sera en LAN (en réseau local), et non sur Internet. Vous serez donc le seul à pouvoir y accéder. Si vous voulez créer un serveur Internet, il vous faudra taper sv_lan 0 dans la console ;) .
Justement, parlons de la console ! Si vous faites une map solo pour HL², il n'y a pas d'option de création d'un serveur. Vous devrez taper ceci dans la console : map nom_de_votre_map, sans l'extension.
Moi je n'ai pas de console, comment j'y accède ?
Ah, dans ce cas, allez dans le volet de Steam qui contient tous vos jeux. Cliquez droit sur votre mod, et cliquez sur Properties (Propriétés). Ensuite, cliquez sur Set launch options (Options de lancement), et indiquez -console :
Dorénavant, quand vous lancerez votre mod préféré, la console sera présente ;) .
Avant de compiler, il y a quelque chose de très important à faire avec Hammer : Alt + P.
Hammer va alors vous lister les erreurs qu’il trouve, comme les blocs avec des formes invalides, des erreurs d’angles…
Regardez, ici, j’ai fait exprès de générer des erreurs :
Vous pouvez cliquer sur chaque problème, et Hammer vous mènera au lieu de l’erreur. Généralement, vous pourrez cliquer sur Fix ou sur Fix all pour qu’Hammer corrige les problèmes.
Cela dit, il faut faire attention aux erreurs liées aux outputs/inputs et aux structures invalides. Dans ces deux cas, Hammer va corriger comme une patate et il vaut mieux que vous le fassiez vous-même. Si vous avez une erreur …has bad I/O connections, c’est un problème d’inputs/outputs et vous devez rétablir les connexions vous-même. Dans la cas d’une structure invalide, il vous faudra très certainement supprimer le bloc et le recréer ;) .
Normalement, après chaque compilation, vous devez inspecter votre log de compilation, via Hammer. Ca doit être un réflex de façon à trouver les éventuelles erreurs.
Ce n’est pas facile de s’y retrouver, mais généralement, les erreurs sont bien visible (Warning, Couldn’t machin truc, Leak, Error…).
Pour vous aider, un membre de Mapping-Area, NykO18 [MA] a créé un petit script qui analyse votre log et qui vous dit s’il y a des erreurs. C’est très pratique pour le débutant :) .
La page Web se trouve ici. Il vous suffit de coller votre log de compilation dans la zone de texte puis cliquez sur Vérifier.
Le script va alors vous lister toutes vos erreurs, en vous les expliquant, ou vous dire qu’il n’y a pas d’erreur :) . C’est vraiment bien fait, et je dois dire que les conseils donnés m’ont aidé à de nombreuses reprises. Comme je trouve ce système vraiment complet, je ne vais pas vous lister toutes les erreurs et toutes les méthodes de résolution.
Cela dit, vous pouvez vous rendre ici pour visualiser toutes les erreurs recensées :) .
Il se peut que votre map plante lors du lancement du serveur. Si c'est le cas, vous devez lancer la map avec la console (mettez map nom_de_la_map sans l'extension), et regardez ce qui s'inscrit dans la console. Il y a de fortes chances pour que le problème y apparaisse.
Voici par exemple ce que me donne la console pour une de mes maps :
Dès que vous avez repéré le problème, résolvez-le si vous y arrivez, ou recherchez sur Google. Il y a de fortes chances pour que votre problème soit courant (il y en a tellement que je ne peux pas vous les lister) ;) .
Le leak est le bug le plus courant, et peut parfois être un vrai calvaire. Pour rappel, le leak est un trou dans votre map, trou qui laisse voir le vide.
Regardez, sur le screen ci-dessous, j'ai fait exprès de faire un leak :
Quand dans votre compilation, VBSP vous informe que vous avez un leak, un fichier nom_de_la_map.lin est créé. C'est ce que l'on appelle le pointfile.
Maintenant, allez dans le menu Map de Hammer. Cliquez ensuite sur Load Pointfile. Validez la boîte de dialogue qui s'affiche, et observez bien vos vues 2D et 3D :
Un trait rouge est apparu. Il ne vous reste plus qu'à suivre ce trait jusqu'à l'endroit où il sort de la map. A cet endroit se trouve votre leak ;) .
Le cordon tool, ou plutôt l'outil cordon est un petit outil très utile qui permet de ne compiler qu'une seule partie de la map. Ainsi, vous pouvez compiler votre map par parties de façon à trouver l'emplacement d'une erreur persistante.
Je reprendrai ma map avec la piscine et vais faire comme si je recherchais mon leak. Pour cela, je vais compiler la moitié de la map pour savoir si le leak se trouve dans cette demi-map.
Pour cela, prenez l'outil cordon :
. Avec celui-ci, nous allons définir la moitié de la map à compiler :
Dès que votre zone de sélection est bien en place, vous pouvez cliquer sur
histoire de voir, dans votre vue 3D, ce qui sera compilé.
Maintenant, compilez, avec seulement le VBSP (puisque je recherche une erreur de leak, je n'ai donc pas besoin de VRAD et de VVIS).
Si il n'y a pas de leak, ça veut dire que le leak se trouve dans la moitié non prise en compte. Ca vous donne donc une idée de l'endroit où chercher. Dans ce cas, sélectionnez avec le cordon la moitié de la partie qui contient le leak. A force de compiler des moitiés de moitiés de map, vous allez trouver avec précision l'endroit où se trouve le leak.
Le VISGroup est une fonction de Hammer qui permet de cacher certains éléments de la map, pour en faciliter la création. Par exemple, si vous mettez plein de blocs CLIP, de l'eau, des func_details... vous pouvez choisir de les masquer sous Hammer, et ainsi mieux vous y retrouver dans la création de votre map, surtout dans les vues 2D.
Hammer crée lui-même toute une série de VISGRoups en fonction de ce qui se trouve dans la map, comme les displacements, les func_datails, les blocs avec la texture CLIP, du NODRAW, les blocs d'eau, les entités point... Bref, Hammer recense les différents types d'éléments qui se trouvent dans votre map.
Le panneau qui permet de visualiser ces éléments se nomme VISGroup. Il se trouve dans la colonne de droite de Hammer. Le panneau est composé de deux onglets : User et Auto.
User : affiche les VISGroups que vous avez créé vous-même
Auto : affiche les VISGroups que Hammer a créé
Voici à quoi peuvent ressembler les deux onglets en ouvrant une map :
Euh... Moi je n'ai pas de panneau VISGroup... Je fais comment ?
Bin, c'est tout simple : allez dans le menu View, puis Screen Elements, et cochez Filter Control.
Comme vous le voyez, Hammer a plutôt bien organisé les différentes catégories et sous-catégories. Si vous voulez masquer tous vos triggers, par exemple, il vous suffit de décocher l'item Triggers, et les triggers ne seront plus affichés dans vos vues 3D et 2D. Donc en fait, il n'y a rien de bien compliqué là-dedans. Nous allons maintenant voir comme créer vos propres VISGroups :) .
Pour créez un VISGroup, cliquez sur le bouton Edit, dans le bas du panneau. Un panneau d'édition s'ouvre.
Pour créer un VISGroup, cliquez sur le bouton New group. Un nouveau groupe apparaît alors dans le bas de l?arborescence. Cliquez dessus, et dans le champ situé dans le haut à droite du panneau, entrez un nom pour ce nouveau VISGroup. Maintenant que cela est fait, cliquez sur Close pour fermer le panneau.
Faire des sous-catégories
Vous avez la possibilité de créer des sous-catégories. Par exemple, j'ai créé le VISGroup Respawn. Dedans, je souhaite créer deux sous-VISGroup : Red et Blue. Pour cela, il suffit de créer les deux VISGroups Red et Blue à la suite du VISGroup Respawn, comme ceci :
Fermez cette fenêtre et retournez sous l'onglet User. Pour déplacer Red et Blue, il suffit de les sélectionner (un par un, on ne sait pas en sélectionner plusieurs en même temps) et de les faire glisser dans le VISGroup Respawn, avec le clic droit de la souris.
Unir deux VISGroup
Il suffit de faire glisser le VISGroup à unir dans un autre, en utilisant le clic gauche.
Ajouter des objets à un VISGroup
Maintenant, il faut ajouter des objets dans un VISGroup pour pouvoir les masquer. Ça, c?est tout simple. Cliquez sur un objet (bloc, entité point ou entité bloc), et affichez ses Propriétés (Alt + Enter). Si l?objet en question est juste un bloc, le panneau des Propriétés affiche directement l'onglet VISGroup. Pour une entité point ou une entité bloc, affichez l?onglet VISGroup, qui se trouve en dernière position.
Il vous suffit alors de cocher ce à quel(s) VISGroup votre objet va appartenir. Vous remarquerez aussi qu?il y a la possibilité d?éditer les VISGroup directement avec ce panneau (bouton Edit groups). Fermez le panneau.
Sous Hammer, rien ne change. Pour masquer un VISGroup, il vous suffit de le décocher dans le panneau latéral.
Le bouton Show permet d?afficher tous les VISGroup d?un seul coup, sans pour autant recocher les différents VISGroup préalablement décochés.
Comme vous le savez, Hammer compiler vos fichiers .vmt en fichier .bsp pour qu'ils soient jouables. S'il y a moyen de compiler, il y a aussi moyen de décompiler...
Pour décompiler une map, il faut utiliser un petit utilitaire baptisé BSP Decompiler. Mais avant de vous parler de ça, je vais d'abord vous expliquer le but d'une décompilation.
Oui, pourquoi décompiler une map ?
Il y a trois raisons principales qui peuvent pousser un mappeur à décompiler une map, qu'elle soit officielle ou non :
faire un remix de la map d'origine
comprendre comment le mappeur à fait tel ou tel effet
rechercher des éléments qu'on ne parvient pas à retrouver, comme les models ou des textures
1. La première des 3 raisons est la plus mauvaise ! On n'apprend pas à mapper en décompilant cs_assault, en mettant 3 caisses en plus et en recompilant sous le nom cs_assault_bymoi2008. Ça, c'est faire du plagiat. C'est nul, ça manque d'imagination et ça ne vous procure aucune satisfaction. Malheureusement, cette pratique est très courante, notamment dans le monde de Counter-Strike. D'ailleurs, une petite voix me dit de ne pas expliquer comment décompiler pour cette raison. Mais bon, au fond de moi je pense que les deux autres raisons valent que je m'attarde à vous l'expliquer.
2. Cette deuxième raison est déjà plus louable. C'est en analysant la façon de faire des autres que l'on progresse : les systèmes d'entités, l'optimisation, ou même tout simplement la façon de displacer ou de faire un bon brushwork (travail des blocs).
3. Cette troisième raison est un peu plus tordue. Il m'est déjà arrivé de décompiler une map pour aller récupérer le nom d'un model que je ne parvenais pas à trouver dans l'explorateur de models. Ce n'est pas une raison super importante, mais dans certains cas vous irez plus vite à décompiler/copier-coller un model plutôt que de le rechercher avec le model browser ^^ .
Bon voilà, j'ai fait ma petite mise en garde, et j'espère que vous ne décompilerez pas pour faire un remix boiteux :) ...
Pour décompiler une map, vous avez besoin d'un utilitaire répondant au nom de VMEX, qui signifie Valve Map EXtractor. Cet utilitaire est codé en Java et doit être utilisé en ligne de commande. En tant qu'utilisateur de Windows, c'est quelque chose que nous n'aimons pas ^^ . C'est pourquoi BSP Decompileur a été développé, il fournit une interface graphique à VMEX.
Pour la facilitée, décompilez ces deux archives dans le même dossier. Je vous conseille, pour être ordonné de créer un dossier quelque part dans le répertoire du Source SDK, histoire de tout garder ensemble ^^ .
Une fois que c'est décompilé, ouvrez BSP Decompileur. Vous devriez obtenir ceci :
Cliquez sur le mot Modifier pour indiquer au programme où se trouve VMEX. Dans la fenêtre d'exploration, recherchez le fichier vmex.jar puis cliquez sur Ouvrir.
Utilisation
Une fois que c'est fait, le programme est prêt. Il ne vous reste plus qu'à cliquer sur Ouvrir pour recherche le fichier .bsp à décompiler, puis à cliquer sur Chercher pour spécifier le nom du fichier .vmf (la map décompilée donc). Ensuite, cliquez sur Décompiler ; une console qui montre l'évolution de la décompilation s'ouvre.
Et voilà, vous pourrez ouvrir la map décompilée avec Hammer :) .
A la base, GCF signifie Grid Cache File (Grid était le nom de code de Steam). Avec le temps le sens a changé pour devenir Game Cache File. Les fichiers GCF font office de containers : ils contiennent des fichiers dont Steam et les différentes applications qui gravitent autour ont besoin. Par exemple, le fichier half-life 2 content.gcf contient les fichiers de base de Half-Life².
Les GCF sont utilisés par Steam car ils sont faciles à mettre à jour, car ils réservent une place sur le disque dur pour contenir les nouveaux fichiers, ce qui limite fortement la fragmentation.
Pourquoi parler de ça ?
Les GCF contiennent donc des fichiers qu'il est parfois intéressant de récupérer, comme des sons, des textures des models ou tout simplement des maps si vous voulez les décompiler. Remarquez que seuls les jeux et les mods officiels utilisent des GCF, les mods officieux ne les utilisent pas.
Les fichiers GCF sont tous contenus dans le même répertoire : C:\Program Files\Steam\steamapps. Par défaut, Windows ne peut ouvrir ces fichiers, il va donc falloir utiliser un petit utilitaire : GCFScape.
Ouvrez votre dossier steamapps et sélectionnez un fichier GCF à ouvrir, et double-cliquez dessus. Pour l'exemple j'ouvre counter-strike source shared.gcf qui contient la quasi totalité des fichiers de Counter-Strike Source (pour la version anglaise). GCFSCape s'ouvre. Comme vous le voyez, l'interface ressemble fortement à l'explorateur Windows. Vous pouvez alors évoluer dans les différents dossiers pour rechercher ce dont vous avez besoin :
J'ai trouvé la map cs_militia.bsp. Pour pouvoir ouvrir un fichier, il faut l'extraire du GCF. Pour cela, cliquez-droit sur le fichier à récupérer et cliquez sur Extract. Vous pouvez bien entendu extraire plusieurs fichiers en même temps. Après avoir cliqué sur Extract, le programme vous demande où il doit placer les fichiers extraits.
Vous pouvez aussi, comme avec un utilitaire comme WinZip ou WinRar, faire un glisser-déplacer du ou des fichiers à extraire vers l'explorateur Windows. Cependant, je vous le déconseille, ça m'est déjà arrivé de faire planter et GCFScape et l'explorateur en faisant ça ^^ .
Durant l'installation décochez la case qui propose de démarrer ATI Tray Tools au démarrage de l'ordinateur, ce n'est pas utile.
Quand c'est installé, démarrez-le. Il se peut qu'il refuse de démarrer en prétextant qu'il n'a pas assez d'autorisations pour accéder au driver de la carte graphique. Si c'est le cas, cliquez droit sur le programme atitray.exe (quand le dossier d'installation) et sous l'onglet Compatibilité, cochez l'option Exécuter ce programme en tant qu'administrateur. Si la case est grisée, cliquez sur le bouton Modifier les paramètres pour tous les utilisateurs.
Une fois ATI Tray Tools démarré, cliquez droit sur l'icône dans la zone de notification. Allez dans Direct 3D, puis Options additionnelles, et cochez Centre alternatif de pixels.
Lancez Hammer, et le problème devrait être résolu.