Attention : cet article a été écrit pour le SDK 2.2 d'Half-Life 1 ! Il se peut qu'il ne soit pas entièrement compatible avec des versions antérieures ou supérieures du Kit.

Introduction

Ce tutorial a pour but de vous montrer comment créer une simple visée laser telle que celle du lance-roquettes d'Half-life. Pour cela, on va admettre qu'on activera et désactivera notre visée laser avec le second mode de tir de l'arme.

Notre tâche va être grandement simplifiée puisqu'on va justement pouvoir reprendre la classe CLaserSpot originellement créée spécialement pour le RPG.

Visée laser OFF Visée laser ON

Let's go!

Comme je l'ai évoqué juste au-dessus, la visée laser du RPG est constituée d'une entité (matérialisée par un sprite) représentant le point d'impact du laser contre quelque chose de solide. Ce point est appelé « laser dot », d'où sa classe CLaserSpot.

On va donc avoir besoin d'un objet de cette classe pour notre arme. Allez à la définition de classe de votre arme (normalement dans weapon.h) et rajoutez-y ces deux variables membres publiques :

public:
  // laser dot
  CLaserSpot *m_pSpot;
  bool m_bSpotActive

La seconde variable est un flag indiquant si le laser est actif ou pas. On va également créer un nouvelle fonction pour afficher le « laser dot ». Ajoutez à la classe de votre arme la déclaration de cette nouvelle fonction membre :

void UpdateSpot ();

Maintenant déplacez vous vers le fichier source de votre arme et initialisons notre flag dans la fonction Spawn() (en admettant que la classe de votre arme s'appelle CMonArme) :

// --------------------------------------------------------------------------
// CMonArme::Spawn
// --------------------------------------------------------------------------

void
CMonArme::Spawn ()
{
  m_bSpotActive = false;

  // ... reste du code de la fonction ...
}

Définisions maintenant la fonction que l'on vient de créer :

// --------------------------------------------------------------------------
// CMonArme::UpdateSpot
// --------------------------------------------------------------------------

void
CMonArme::UpdateSpot ()
{
#ifndef CLIENT_DLL
  if (m_bSpotActive)
    {
      if (!m_pSpot)
        m_pSpot = CLaserSpot::CreateSpot ();

      UTIL_MakeVectors (m_pPlayer->pev->v_angle);
      Vector vecSrc = m_pPlayer->GetGunPosition ();
      Vector vecAiming = gpGlobals->v_forward;

      TraceResult tr;
      UTIL_TraceLine (vecSrc, vecSrc + vecAiming * 8192,
                      dont_ignore_monsters, ENT (m_pPlayer->pev), &tr);

      UTIL_SetOrigin (m_pSpot->pev, tr.vecEndPos);
    }
#endif
}

Cette fonction s'assure que tout d'abord que le « laser dot » est bien créé. Si ce n'est pas le cas, on appelle la fonction CLaserSpot::CreateSpot(). Ensuite on construit une ligne virtuelle à partir des coordonnées de l'arme et de l'endroit visé pour déterminer la position du spot, lequel on met à jour en appelant UTIL_SetOrigin().

Notez également que l'on s'assure de ne pas refaire deux fois la même chose : on désactive cette partie du code du côté DLL client.

Cette fonction, on va l'appeler deux fois : au début de PrimaryAttack() et de WeaponIdle(). Modifiez donc ces fonctions pour qu'elles mettent à jour le « laser dot » :

// --------------------------------------------------------------------------
// CMonArme::PrimaryAttack
// --------------------------------------------------------------------------

void
CMonArme::PrimaryAttack ()
{
  UpdateSpot ();

  // ... reste du code de la fonction ...
}

// --------------------------------------------------------------------------
// CMonArme::WeaponIdle
// --------------------------------------------------------------------------

void
CMonArme::WeaponIdle ()
{
  UpdateSpot ();

  // ... reste du code de la fonction ...
}

On va maintenant passer à l'activation et désactivation du laser. Modifiez la fonction SecondaryAttack() de sorte à ce qu'elle ressemble à ceci au code suivant. Si vous avez déjà un second mode de tir, vous pouvez aménager votre fonction pour qu'elle accepte et votre second mode de tir, et le laser.

// --------------------------------------------------------------------------
// CMonArme::SecondaryAttack
// --------------------------------------------------------------------------

void
CMonArme::SecondaryAttack ()
{
  m_bSpotActive = !m_bSpotActive;

#ifndef CLIENT_DLL
  if (!m_bSpotActive && m_pSpot)
    {
      m_pSpot->Killed (NULL, GIB_NORMAL);
      m_pSpot = NULL;
    }
#endif

  m_flNextSecondaryAttack = UTIL_WeaponTimeBase () + 0.2;
}

Si le laser est désactivé, on détruit l'entité. S'il est désactivé, on change simplement le flag m_bSpotActive et l'entité sera recrée lors du prochain appel de UpdateSpot().

Il reste enfin une dernière chose à faire : désactiver le « laser dot » s'il est activé lorsque le joueur change d'arme. Pour cela on fait une petite vérification dans la fonction Holster() :

// --------------------------------------------------------------------------
// CMonArme::Holster
// --------------------------------------------------------------------------

void
CMonArme::Holster (int skiplocal /* = 0 */)
{
  // ... reste du code de la fonction ...

#ifndef CLIENT_DLL
  if (m_pSpot)
    {
        m_pSpot->Killed (NULL, GIB_NEVER);
        m_pSpot = NULL;
    }
#endif
}

Et voilà ! Il ne vous reste plus qu'à recompiler mp.dll et client.dll.

Vous pouvez aussi désactiver le laser un espace de temps et le réactiver ensuite en utilisant les fonctions suivantes (déjà déclarées et définies dans CLaserSpot) :

void Suspend (float flSuspendTime);
void EXPORT Revive ();
Creative Commons Logo Contrat Creative Commons

Cet article est mis à disposition sous un contrat Creative Commons (licence CC-BY-ND).