Article     Discussion     Modifier     Historique     Forums     Salon IRC

Half-Life 1, Augmenter le nombre maximum d'armes gérées

Un article de Games Creators Network.


Suivant l’opinion de la communauté, j’ai longtemps cru que la limite du nombre d’armes n’était pas franchissable, mais c’est seulement quand je me suis vraiment posé la question que j’ai compris que c’est possible car nous avons dans le SDK tout le code des armes de A à Z avec cependant une petite subtilité.

Dans ce tutorial je ne livrerais pas texto quoi écrire mais je vous montrerai tous ce qu’il vous faut savoir pour y parvenir. Mon objectif est avant tout de vous faire comprendre ce que vous allez coder.

[modifier] Modification du serveur

Vous connaissez sûrement déjà :

#define MAX_WEAPONS 32

Mais nous voulons:

#define MAX_WEAPONS 64

En modifier cela Half-Life démarre mais nous ne pouvons pas savoir si notre arme 48 fonctionne car le menu des armes disparaît... Ceci nous invite à observer comment les armes sont transférer au client. En recherchant un peu on trouve :

MESSAGE_BEGIN( MSG_ONE, gmsgWeaponList, NULL, pev );  
	WRITE_STRING( pszName );
	WRITE_BYTE( GetAmmoIndex( II.pszAmmo1 ));
	WRITE_BYTE( II.iMaxAmmo1 );
	WRITE_BYTE( GetAmmoIndex( II.pszAmmo2 ));
	WRITE_BYTE( II.iMaxAmmo2 );
	WRITE_BYTE( II.iSlot );
	WRITE_BYTE( II.iPosition );
	WRITE_BYTE( II.iId );
	WRITE_BYTE( II.iFlags );
MESSAGE_END();

Donc nous observons que le slot, la position et l’ID de l’arme est envoyée. L’ID est envoyé avec un BYTE soit 1 octet ce qui permet d’accepter un nombre jusqu'à 255. Donc pas de problème.

Alors si le réseau n’est pas en cause c’est peut-être que le serveur ne peut pas stocker plus de 32 alors. Voyons comment les armes sont conserver. De base pour la grenade nous pouvons trouver quelques choses de proche de ça:

void GcGrenade::Holster( int skiplocal )
{
 if( !m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
 {
  m_pPlayer->pev->weapons &= ~( 1<<Gm_GRENADE_ID );
  SetThink( DestroyItem );
  pev->nextthink = gpGlobals->time + 0.1;
 }
}

Ceci signifie que nous n’avons plus de munitions, l’arme est supprimée, ce qui nous fait dire que les armes sont sauvées dans pev->weapons en tant que bit de weapons. ( J’appelle ça des options binaires mais en fait, je ne connais pas la bonne dénomination ). A chaque bit de pev->weapons correspond une arme et comme nous sommes limiter à 32 armes, weapons est probablement un int. Pour vérifier direction progdefs.h dans le répertoire engine du source. On y trouve la déclaration de la structure entvars_s ,type de pev, qui confirme que weapons est du type int. Pour autoriser 64 armes vous avez peut être pensé à changer le type de weapons en __int64, malheureusement ceci aura pour effet de crasher HL.EXE car il doit probablement utiliser cette structure et en la modifiant, elle se trouve différente entre notre code et celui de HL.EXE. Ce n’est en fait qu’un mince problème car il nous suffit de créer une variable adaptée directement dans la classe CbasePlayer où nous sauverons les armes selon la méthode de notre choix. Pour ceci je vous invite à lire, le .cpp ci-joint qui traite de plusieurs méthodes pour conserver nos armes.

[modifier] Modification du client

Nous avons vu plus haut que gmsgWeaponList envoyait les armes au client. Alors nous allons observer la réception niveau client c’est à dire la fonction MsgFunc_WeaponList( ) et la tout semble bien convenablement sauver mais pourtant notre menu des armes est toujours invisible ... Avec une petite recherche de iId où est transférer l’ID de chaque armes nous apercevons bien vite que les armes sont sauver dans m_iWeaponBits et le HUD est actualiser quand iOldWeaponBits et m_iWeaponBits sont différent. Remplacer c’est deux variables par le système de conservation des armes de votre choix ( cf. .cpp ) Cependant le HUD ne sera toujours pas visible ! Si vous avez fait bien attention dans votre rechercher de m_iWeaponBits vous aurez remarquez ceci:

m_iWeaponBits = cdata->iWeaponBits;

Cette ligne bien étrange dans la mesure où la variable iWeaponBits n’est inscrite nulle part dans le code à part dans la déclaration de sa structure client_data_s et à cette ligne... Plus étrange encore m_iWeaponBits ne subit aucune affectation de saut à cette ligne or c’est cette variable qui contrôle également l’affichage du HUD...

Mes déductions ? En réalité il n’y a pas un seul transfert réseau mais 2. Le premier c’est celui de l’ID des armes via gmsgWeaponList et le seconde c’est celui de pev->weapons via HL.EXE vers casa->iWeaponBits, donc en n’utilisant plus pev->weapons nous avons non seulement surpasser une contrainte du SDK nous nous sommes libérer d’une limite du SDK car le transfert n’est plus géré par HL.EXE mais par nous ! Il est également remarquable que le transfert de pev->weapons est quelques peu stupide car les armes sont déjà transférée via leur ID. C’est donc à vous de réalisez l’affectation des armes dans m_iWeaponBits ce qui est une chose plutôt triviale. Vous pouvez par exemple profiter de gmsgWeaponList pour cette opération et à chaque récupération d’armes utilisez MsgFunc_WeapPickup( ).


[modifier] C’est à vous de jouer

Comme promis, je me suis contenter de vous donnez toutes les indications pour le réaliser vous-même votre gestion des armes ainsi que quelques solutions de stockages, il vous faut savoir programmer un minimum en C/C++ et vous ne devriez pas avoir de problèmes. Si vous avez des suggestions, des idées pour conserver les armes ou optimiser mon code, ou même des questions [1]

Ce document a été publié sur la version 3 du G.C.N. par Groove.

  • Auteur Original : Groove
  • Date de publication : 8 mai 2002

 

Rechercher
Installer l'extension de recherche Plus d'informations

 

Comprendre
Tu me dis, j'oublie. Tu m'enseignes, je me souviens. Tu m'impliques, j'apprends. - Benjamin Franklin

 

Partager
La connaissance est la seule chose qui s'accroit lorsqu'on la partage. - Sacha Boudjema

 

Créer
L'imagination est plus importante que la connaissance. - Albert Einstein

 

 

Le wiki en images Le wiki en images Image du mois: «Snowball: un prototype de jeu développé avec NeL.