=(News )==( Fichiers )==( Tutoriaux et Astuces )==( Liens )=

 Un Premier Plugin TPP 

 

 

 

 

 

Faire une dll de TPP pour les nuls ( par un nul )
Un Tutorial de Un Type

Le but de ce tutorial n'est pas de faire de vous un crack de la programation en C++, mais juste de vous donner quelques bases qui vous permettrons la créations de dlls assez simples pour TPP.

1- Algorithme

Si vous n'avez jamais fait de programation, que vous ignorez le role d'une fonction, d'une variable, d'une procédure, d'une structure : Il est temps de vous retrousser les manches :

Direction : http://aigespc57.cicrp.jussieu.fr/algo/index.htm

Pourquoi apprendre l’algorithmique pour apprendre à programmer ? En quoi a-t-on besoin d’un langage spécial, distinct des langages de programmation compréhensibles par les ordinateurs ?

Parce que l’algorithmique exprime les instructions résolvant un problème donné indépendamment des particularités de tel ou tel langage. Pour prendre une image, si un programme était une dissertation, l’algorithmique serait le plan, une fois mis de côté la rédaction et l’orthographe. Or, vous savez qu’il vaut mieux faire d’abord le plan et rédiger ensuite que l’inverse…

Apprendre l’algorithmique, c’est apprendre à manier la structure logique d’un programme informatique. Cette dimension est présente quelle que soit le langage de programmation ; mais lorsqu’on programme dans un langage (en C, en Visual Basic, etc.) on doit en plus se colleter les problèmes de syntaxe, ou de types d’instructions, propres à ce langage. Apprendre l’algorithmique de manière séparée, c’est donc sérier les difficultés pour mieux les vaincre.

A cela, il faut ajouter que des générations de programmeurs, souvent autodidactes (mais pas toujours, hélas !), ayant directement appris à programmer dans tel ou tel langage, ne font pas mentalement clairement la différence entre ce qui relève de la structure logique générale de toute programmation (les règles fondamentales de l’algorithmique) et ce qui relève du langage particulier qu’ils ont appris. Ces programmeurs, non seulement ont beaucoup plus de mal à passer ensuite à un langage différent, mais encore écrivent bien souvent des programmes qui même s’ils sont justes, restent laborieux. Car on n’ignore pas impunément les règles fondamentales de l’algorithmique… Alors, autant l’apprendre en tant que telle !

2- Le C++ : introduction

Bon, alors une fois les notions d'algo aquises, je vous conseille de jetter un oeil ici :

http://www.developpez.biz/downloads/c/tutoriels/cours_cpp.pdf

 

3- Let's go !

C'est fait, vous avez a présent vos marques ? On va pouvoir commencer a s'y mettre serieusement

Le but de ce tutorial va etre de creer un plugin de TPP qui, lorsqu'il intercepte .hello prononcé en local, envoit un message systeme "Bonjours".

C'est surement un peu con, mais je suis sur que ca peut permettre a certains une premiere approche.

Vous avez besoin pour ce cours de plusieurs choses :

  • TPP ( ici )
  • Le TPP plugin wizard ( ici )
  • Visual C++ ( Débrouillez vous pour le trouver )
  • TPP Tools Lite ( ici )

Vous avez tout le matériel ? Ok alors on y va :

Placez le TPP plugin Wizard dans Microsoft Visual Studio/Common/MSDev98/Template

Puis lancez Visual C++, faites File -> New et vous devriez avoir cette fenetre :

Bien sur ici on selectionne le wizard TPP, on donne un nom au projet et on selectionne son emplacement.

Dans l'ecran suivant, on vous demande si vous voullez utiliser les MCF. Libre a vous de répondre comme vous le souhaitez.

Enfin le wizard nous demande quelles fonctions nous comptons utiliser ... dans notre exemple, nous allons choisir cela :

Et voila, le squelette de notre dll a été généré.

Premiere chose a faire, on se rend dans Build -> Set Active Configuration et on se met en mode release

Sinon, les dll vont bugger ...

On remarque cela :

void *fnProcessOut(unsigned char *pak_buffer, DWORD &taille, DWORD &param)
{
param=PLUGIN_PAK_NOCHANGE;

return pak_buffer;
}

fnProcessOut, c'est la fonction qui recoit tous les paks envoyés par notre client ( au passage, fnProcessIn, c'est les paks envoyés par le serveur )

Le but ici est d'intercepter les paks prononcé en local et contenant un texte bien précis

Comment est composé le pak que le client envoit pour parler en local ?

Voila un de ce spaks, capturés a l'aide du plugin LogPak :

24 Jul 03 07:17:42 - Client: Pak 027: RQ_IndirectTalk, lg=16
24 Jul 03 07:17:42 - 00 1B 00 00 08 2A 00 00 00 BE BE 00 03 68 6F 70 : .....;.......hop

Et voila comment sont composé les pak IndirectTalk :

Pak 027 : RQ_IndirectTalk
00.l : ID de l'emetteur
04.b : Direction de l'emeteur
05.l : Couleur du texte
09.w : Nombre de caracteres du texte
11.x : Texte

Décomposons ensemble ce : 00 1B 00 00 08 2A 00 00 00 BE BE 00 03 68 6F 70

00 1B correspond au type du pak : 001B en hexa correspond a 27 en décimal

00 00 08 2A correspond a l'id du perso qui parle

00 correspond a la direction de l'emeteur

00 00 BE BE a la couleur du texte

00 03 correspond au nombre de caracteres que l'on va prononcer

68 6F 70 correspond a hop en ASCII

Donc pour detecter .hello, nous allons tapper :

 


void *fnProcessOut(unsigned char *pak_buffer, DWORD &taille, DWORD &param)
{
   param=PLUGIN_PAK_NOCHANGE;
   int type;

   //type va contenir le type du pak envoyé par le client
   type=*(short *)pak_buffer;

   //Si le pak est un indirect Talk
   if (type==0x1B00)
      {

      //ici on va lire la partie contenant le texte du pak, si cela correspond a .hello ( qui fait 6 caracteres ) alors le test est validé
      if (!strnicmp((char *)&pak_buffer[13],".hello",6))
         {
         //ici on va utiliser une des fonctions générés par le Wizard de TPP, la fonction Send_sysmsg qui va permettre d'envoyer un message bleu a notre client.
         Send_sysmsg("Bonjours");

         //ici on va délete le pak pour qu'il ne s'affiche pas sur notre tete, il va donc etre intercepté et effacé par TPP
         param=PLUGIN_PAK_DELETE;
         }
      }
   return pak_buffer;
}



A présent on appuis sur F7, ca va compiler le tout.

Puis on copie la dll présente dans le répertoire Release vers le répertoire des dll de TPP et on peut enfin tester nous meme ce plugin.

A présent, on va ajouter une petite chose a la dll : Il faut que cette derniere puisse dire Bonjours sur le main.

Le pak a envoyer est le suivant : 00 31 00 04 4D 61 69 6E 00 08 42 6F 6E 6A 6F 75 72 73

On recopie ca dans TPP tools lite pour creer la commande adéquate sans se prendre la tete :

Donc dans la case du haut on met le pak a générer, puis on clique sur Creer Commande.

Et on récupere :

unsigned char pak[18]={0x00, 0x31, 0x00, 0x04, 0x4D, 0x61, 0x69, 0x6E, 0x00, 0x08, 0x42, 0x6F, 0x6E, 0x6A, 0x6F, 0x75, 0x72, 0x73};

thisplug.fnSendOut(pak, 18, true);

Donc au final pour envoyer un bonjours sur le main quand qq on tappera la commande .hello cela demandera le code suivant :

 


void *fnProcessOut(unsigned char *pak_buffer, DWORD &taille, DWORD &param)
{
   param=PLUGIN_PAK_NOCHANGE;
   int type;

   //type va contenir le type du pak envoyé par le client
   type=*(short *)pak_buffer;

   //Si le pak est un indirect Talk
   if (type==0x1B00)
      {

      //ici on va lire la partie contenant le texte du pak, si cela correspond a .hello ( qui fait 6 caracteres ) alors le test est validé
      if (!strnicmp((char *)&pak_buffer[13],".hello",6))
         {
         //ici on va utiliser une des fonctions générés par le Wizard de TPP, la fonction Send_sysmsg qui va permettre d'envoyer un message bleu a notre client.
         Send_sysmsg("Bonjours");

         unsigned char pak[18]={0x00, 0x31, 0x00, 0x04, 0x4D, 0x61, 0x69, 0x6E, 0x00, 0x08, 0x42, 0x6F, 0x6E, 0x6A, 0x6F, 0x75, 0x72, 0x73};
         thisplug.fnSendOut(pak, 18, true);

         //ici on va délete le pak pour qu'il ne s'affiche pas sur notre tete, il va donc etre intercepté et effacé par TPP
         param=PLUGIN_PAK_DELETE;
         }
      }
   return pak_buffer;
}


Au cas ou vous avez un probleme, téléchargez la source de cette dll ici

Bon, félicitation, vous vennez de faire votre premier Plugin pour TPP, c'est pas grand chose, mais c'est déja un bon début :)

 

4- Quelques bouts de codes sources qui peuvent etre utile

 


//Fonction : Envoyer un message systeme :

void Send_sysmsg(LPCTSTR msg,...)
{
   int      lg_msg;
   CString  message;
   char  *pak;

   if (thisplug.fnSendIn != NULL)
   {
      va_list args;
      va_start(args, msg);
      message.FormatV(msg, args);

      lg_msg=message.GetLength();
      pak=new char[lg_msg+8];

      *(unsigned short *)&pak[0]=0x3F00;  // Message systeme
      *(unsigned short *)&pak[2]=0x1E00;  // ???
      *(unsigned short *)&pak[4]=0x0300;  // ???
      pak[6]=(lg_msg/256)&0xff;        // Longueur du message
      pak[7]=lg_msg&0xff;
      strncpy(&pak[8],message,lg_msg);

      // Envoie le message au client
      thisplug.fnSendIn(pak,lg_msg+8,false);
      delete pak;
   }
}

//Fonction : envoyer un wisp
void Send_page(LPCTSTR dst, LPCTSTR msg)
{
   unsigned char  *pak;
   int            lg_nom,lg_msg;

   lg_nom=strlen(dst);
   lg_msg=strlen(msg);

   pak=new unsigned char[lg_nom+lg_msg+6];

   pak[0]=0x00;
   pak[1]=0x1D;

   pak[2]=lg_nom/256;
   pak[3]=lg_nom&0xFF;
   strncpy((char *)pak+4, dst, lg_nom);

   pak[4+lg_nom]=lg_msg/256;
   pak[4+lg_nom+1]=lg_msg&0xFF;
   strncpy((char *)pak+4+lg_nom+2, msg, lg_msg);

   thisplug.fnSendOut(pak,lg_nom+lg_msg+6,true);

   delete pak;
}

void Send_CCtalk(LPCTSTR cc, LPCTSTR msg)
{
      unsigned char  *pak;
   int            lg_cc,lg_msg;

   lg_cc=strlen(cc);
   lg_msg=strlen(msg);

   pak=new unsigned char[lg_cc+lg_msg+6];

   pak[0]=0x00;
   pak[1]=0x31;

   pak[2]=lg_cc/256;
   pak[3]=lg_cc&0xFF;
   strncpy((char *)pak+4, cc, lg_cc);

   pak[4+lg_cc]=lg_msg/256;
   pak[4+lg_cc+1]=lg_msg&0xFF;
   strncpy((char *)pak+4+lg_cc+2, msg, lg_msg);

   thisplug.fnSendOut(pak,lg_cc+lg_msg+6,true);
   delete pak;
}


//Fonction Envoyer un sort :
void Send_spell(int IDSpell, int X, int Y, int IDcible)
{
   unsigned char pak[12]={0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

   // ID du sort
   pak[2]=(IDSpell>>8) & 0xff;
   pak[3]=IDSpell & 0xff;

   // Crd X de la cible
   pak[4]=(X>>8) & 0xff;
   pak[5]=X & 0xff;

   // Crd X de la cible
   pak[6]=(Y>>8) & 0xff;
   pak[7]=Y & 0xff;

   // ID de la cible
   pak[8]=(IDcible>>24) & 0xff;
   pak[9]=(IDcible>>16) & 0xff;
   pak[10]=(IDcible>>8) & 0xff;
   pak[11]=IDcible & 0xff;

   thisplug.fnSendOut(pak, 12, true);
}

//Detecter les coordonnée X et Y d'un pj/monstre a l'ecran
//Note : Nécéssite d'enregistrer PlayerposX et PlayerPosY comme variable globale
void *fnProcessIn(unsigned char *pak_buffer, DWORD &taille, DWORD &param)
{
   param=PLUGIN_PAK_NOCHANGE;
   int type;
   type=*(short *)pak_buffer;
   if (type==0x0100)
   {
      //action
      int idpak=(pak_buffer[8]<<24)+(pak_buffer[9]<<16)+(pak_buffer[10]<<8)+pak_buffer[11];
      if(idpak==PlayerId)
      {
         //enregistre les pos X et Y
         PlayerPosX=(pak_buffer[2]<<8)+pak_buffer[3];
         PlayerPosY=(pak_buffer[4]<<8)+pak_buffer[5];
      }
   }
   return pak_buffer;
}


//Detecter qu'on prononce un texte en local
void *fnProcessOut(unsigned char *pak_buffer, DWORD &taille, DWORD &param)
{
   param=PLUGIN_PAK_NOCHANGE;
   int offset=0,type;
   type=*(short *)pak_buffer;
   if (type==0x1B00)
      offset=13;
   if (type==0x1E00)
      offset=17;
   int special=100;
   if (offset)
      {
         if (!strnicmp((char *)&pak_buffer[offset],"prout",5))
         {
         //Action
         param=PLUGIN_PAK_DELETE;
         }
      }
   return pak_buffer;
}


//Choper l'id de notre propre perso ( non testé )
void *fnProcessIn(unsigned char *pak_buffer, DWORD &taille, DWORD &param)
{
   param=PLUGIN_PAK_NOCHANGE;
   int type;
   type=*(short *)pak_buffer;
   if(type==0x0D00)
   {
      //On chope l'id de notre perso
      int IdPerso=(pak_buffer[3]<<24)+(pak_buffer[4]<<16)+(pak_buffer[5]<<8)+pak_buffer[6];
   }
   return pak_buffer;
}


//Renseigner les infos sur le joueur
class listcomp
{
public:
   int idskill;
   int points;
   int boost;
   int lgtnom;
   int lgtdes;
   LPCTSTR nom;
};


class livresort
{
public:
   int idspell;
   int type_cible;
   int mana;
   int icon;
   int lgtdes;
   int lgtnom;
   LPCTSTR nom;
};

class equipeditem
{
public:
   int type;
   int iditem;
   int lgt;
   LPCTSTR nom;
};

class backpack
{
public:
   int idicon;
   int idunit;
   int iditem;
   int nbritem;
   int lgt;
   LPCTSTR nom;
};

class infoplayer
{
public:
int id;
int posX;
int posY;
int posZ;
int pv;
int pv_max;
int pm;
int pm_max;
int xp;
int xp_left;
int xp_next;
int ca_boost;
int ca;
int force_boost;
int end_boost;
int dex_boost;
int sag_boost;
int intel_boost;
int pts_stat;
int force;
int end;
int dex;
int sag;
int intel;
int lvl;
int pts_comp;
int karma;
//int pv_norm;
int gold;
int nbrequipeditem;
equipeditem equip[15];
int nbritemsac;
backpack itemsac[120];
int nbrspell;
livresort listspell[120];
int nbrskill;
listcomp listskill[120];
};

void *fnProcessIn(unsigned char *pak_buffer, DWORD &taille, DWORD &param)
{
   param=PLUGIN_PAK_NOCHANGE;
   int type;
   type=*(short *)pak_buffer;

   if(type==0x0100 || type==0x0900 || type==0x0D00 || type==0x2100 || type==0x2500 || type==0x2B00 || type==0x2C00 || type==0x3500 || type==0x4300 || type==0x1300 || type==0x1200 ||type==0x3B00 || type==0x3E00 || type==0x2700)
   {
   switch(type)
   {
      case 0x0100:  //Pak 001 : RP_UpdateCoordinates
         if((pak_buffer[8]<<24)+(pak_buffer[9]<<16)+(pak_buffer[10]<<8)+pak_buffer[11]==moi.id)
            {
            //enregistre les pos X et Y
            moi.posX=(pak_buffer[2]<<8)+pak_buffer[3];
            moi.posY=(pak_buffer[4]<<8)+pak_buffer[5];
            }
         break;

      case 0x0900: //RP_SynchronizePlayerCoordinates
         moi.posX=(pak_buffer[2]<<8)+pak_buffer[3];
         moi.posY=(pak_buffer[4]<<8)+pak_buffer[5];
         moi.posZ=(pak_buffer[6]<<8)+pak_buffer[8];
         break;

      case 0x0D00: //Pak 013 : RP_InfoPlayer
         moi.id=(pak_buffer[3]<<24)+(pak_buffer[4]<<16)+(pak_buffer[5]<<8)+pak_buffer[6];
         moi.posX=(pak_buffer[7]<<8)+pak_buffer[8];
         moi.posY=(pak_buffer[9]<<8)+pak_buffer[10];
         moi.posZ=(pak_buffer[11]<<8)+pak_buffer[12];
         moi.pv=(pak_buffer[13]<<24)+(pak_buffer[14]<<16)+(pak_buffer[15]<<8)+pak_buffer[16];
         moi.pv_max=(pak_buffer[17]<<24)+(pak_buffer[18]<<16)+(pak_buffer[19]<<8)+pak_buffer[20];
         moi.pm=(pak_buffer[21]<<8)+pak_buffer[22];
         moi.pm_max=(pak_buffer[23]<<8)+pak_buffer[24];
         moi.xp=(pak_buffer[25]<<56)+(pak_buffer[26]<<48)+(pak_buffer[27]<<40)+(pak_buffer[28]<<32)+(pak_buffer[29]<<24)+(pak_buffer[30]<<16)+(pak_buffer[31]<<8)+pak_buffer[32];
         moi.xp_left=(pak_buffer[33]<<56)+(pak_buffer[34]<<48)+(pak_buffer[35]<<40)+(pak_buffer[36]<<32)+(pak_buffer[37]<<24)+(pak_buffer[38]<<16)+(pak_buffer[39]<<8)+pak_buffer[40];
         //Atention : Vérifier si les stats renvoyés sont boostés ou non
         moi.force=(pak_buffer[41]<<8)+pak_buffer[42];
         moi.end=(pak_buffer[43]<<8)+pak_buffer[44];
         moi.dex=(pak_buffer[45]<<8)+pak_buffer[46];
         moi.sag=(pak_buffer[49]<<8)+pak_buffer[50];
         moi.intel=(pak_buffer[51]<<8)+pak_buffer[52];
         moi.gold=(pak_buffer[63]<<24)+(pak_buffer[64]<<16)+(pak_buffer[65]<<8)+pak_buffer[66];
         moi.lvl=(pak_buffer[67]<<8)+pak_buffer[68];
         moi.xp_next=(pak_buffer[69]<<56)+(pak_buffer[70]<<48)+(pak_buffer[71]<<40)+(pak_buffer[72]<<32)+(pak_buffer[73]<<24)+(pak_buffer[74]<<16)+(pak_buffer[75]<<8)+pak_buffer[76];
         break;

      case 0x2100:  //Pak 033 : RP_UpdateLife
         moi.pv=(pak_buffer[2]<<24)+(pak_buffer[3]<<16)+(pak_buffer[4]<<8)+pak_buffer[5];
         moi.pv_max=(pak_buffer[6]<<24)+(pak_buffer[7]<<16)+(pak_buffer[8]<<8)+pak_buffer[9];
         break;

      case 0x2500: //Pak 037 : RP_UpdateLevel
         moi.lvl=(pak_buffer[2]<<8)+pak_buffer[3];
         moi.xp_left=(pak_buffer[4]<<56)+(pak_buffer[5]<<48)+(pak_buffer[6]<<40)+(pak_buffer[7]<<32)+(pak_buffer[8]<<24)+(pak_buffer[9]<<16)+(pak_buffer[10]<<8)+pak_buffer[11];
         //Attention : verifier si les pv max renvoyé sont ceux boosté ou non       
         moi.pv=(pak_buffer[12]<<24)+(pak_buffer[13]<<16)+(pak_buffer[14]<<8)+pak_buffer[15];
         moi.pv_max=(pak_buffer[16]<<24)+(pak_buffer[17]<<16)+(pak_buffer[18]<<8)+pak_buffer[19];
         moi.pm=(pak_buffer[20]<<8)+pak_buffer[21];
         moi.pm_max=(pak_buffer[22]<<8)+pak_buffer[23];
         break;

      case 0x2B00: //Pak 043 : RP_StatsPlayer
         moi.pv=(pak_buffer[2]<<24)+(pak_buffer[3]<<16)+(pak_buffer[4]<<8)+pak_buffer[5];
         moi.pv_max=(pak_buffer[6]<<24)+(pak_buffer[7]<<16)+(pak_buffer[8]<<8)+pak_buffer[9];
         moi.pm=(pak_buffer[10]<<8)+pak_buffer[11];
         moi.pm_max=(pak_buffer[12]<<8)+pak_buffer[13];
         moi.xp=(pak_buffer[14]<<56)+(pak_buffer[15]<<48)+(pak_buffer[16]<<40)+(pak_buffer[17]<<32)+(pak_buffer[18]<<24)+(pak_buffer[19]<<16)+(pak_buffer[20]<<8)+pak_buffer[21];
         moi.ca_boost=(pak_buffer[22]<<8)+pak_buffer[23];
         moi.ca=(pak_buffer[24]<<8)+pak_buffer[25];
         moi.force_boost=(pak_buffer[26]<<8)+pak_buffer[27];
         moi.end_boost=(pak_buffer[28]<<8)+pak_buffer[29];
         moi.dex_boost=(pak_buffer[30]<<8)+pak_buffer[31];
         moi.sag_boost=(pak_buffer[34]<<8)+pak_buffer[35];
         moi.intel_boost=(pak_buffer[36]<<8)+pak_buffer[37];
         moi.pts_stat=(pak_buffer[40]<<8)+pak_buffer[41];
         moi.force=(pak_buffer[42]<<8)+pak_buffer[43];
         moi.end=(pak_buffer[44]<<8)+pak_buffer[45];
         moi.dex=(pak_buffer[46]<<8)+pak_buffer[47];
         moi.sag=(pak_buffer[50]<<8)+pak_buffer[51];
         moi.intel=(pak_buffer[52]<<8)+pak_buffer[53];
         moi.lvl=(pak_buffer[56]<<8)+pak_buffer[57];
         moi.pts_comp=(pak_buffer[58]<<8)+pak_buffer[59];
         moi.karma=(pak_buffer[66]<<8)+pak_buffer[67];
         //moi.pv_norm=(pak_buffer[68]<<8)+pak_buffer[69];
         break;


      case 0x2C00: //Pak 044 : RP_UpdateXP
         moi.xp=(pak_buffer[2]<<56)+(pak_buffer[3]<<48)+(pak_buffer[4]<<40)+(pak_buffer[5]<<32)+(pak_buffer[6]<<24)+(pak_buffer[7]<<16)+(pak_buffer[8]<<8)+pak_buffer[9];
         break;

      case 0x3500: //Pak 053 : RP_UpdateGold
         moi.gold=(pak_buffer[2]<<24)+(pak_buffer[3]<<16)+(pak_buffer[4]<<8)+pak_buffer[5];
         break;

      case 0x4300: //Pak 067 : RP_UpdateMana
         moi.pm=(pak_buffer[2]<<8)+pak_buffer[3];
         break;

      case 0x1200: //RP_BackpackItems
         {
         int cmp=9;
         //Send_sysmsg("ET le train passe");
         moi.nbritemsac=(pak_buffer[7]<<8)+pak_buffer[8];
         for(int i=0;i<=moi.nbritemsac-1;i++)
         {
            moi.itemsac[i].idicon=(pak_buffer[0+cmp]<<8)+pak_buffer[1+cmp];
            moi.itemsac[i].idunit=(pak_buffer[2+cmp]<<24)+(pak_buffer[3+cmp]<<16)+(pak_buffer[4+cmp]<<8)+pak_buffer[5+cmp];
            moi.itemsac[i].iditem=(pak_buffer[6+cmp]<<8)+pak_buffer[7+cmp];
            moi.itemsac[i].nbritem=(pak_buffer[8+cmp]<<24)+(pak_buffer[9+cmp]<<16)+(pak_buffer[10+cmp]<<8)+pak_buffer[11+cmp];
            cmp=cmp+16;
         }
         break;
         }

      case 0x3B00:   // si c'est un Serveur: Pak 059: RP_ItemName
         {
         int idunit=(pak_buffer[2]<<24)+(pak_buffer[3]<<16)+(pak_buffer[4]<<8)+pak_buffer[5];
         for(int i=0;i<=moi.nbritemsac-1;i++)
         {
            if(idunit==moi.itemsac[i].idunit)
            {
               moi.itemsac[i].lgt=(pak_buffer[6]<<8)+pak_buffer[7];

               char *temp2 = new char[moi.itemsac[i].lgt+1];
               memcpy(temp2,pak_buffer+8,moi.itemsac[i].lgt);
               temp2[moi.itemsac[i].lgt] = '\0'; // fin de la chaine
               moi.itemsac[i].nom=temp2;
               //Send_sysmsg("trouvé");
            }
         }
         break;
         }



      case 0x1300: //RP_EquipedItems
         {
         int boucle=-1;
         int sortie=1;
         int cmp=3;
         //Send_sysmsg("ok");

         while(cmp+16<taille)
         {
            sortie=(pak_buffer[6+cmp]<<8)+pak_buffer[7+cmp];
                  boucle=boucle+1;
                  moi.equip[boucle].type=(pak_buffer[4+cmp]<<8)+pak_buffer[5+cmp];
                  moi.equip[boucle].iditem=(pak_buffer[6+cmp]<<8)+pak_buffer[7+cmp];
                  moi.equip[boucle].lgt=(pak_buffer[14+cmp]<<8)+pak_buffer[15+cmp];
                  char *temp = new char[moi.equip[boucle].lgt+1];
                  memcpy(temp,pak_buffer+16+cmp,moi.equip[boucle].lgt);
                  temp[moi.equip[boucle].lgt] = '\0'; // fin de la chaine
                  moi.equip[boucle].nom=temp;

                  //Send_sysmsg(moi.equip[boucle].nom);
                  cmp=cmp+16+moi.equip[boucle].lgt;
         }
         moi.nbrequipeditem=boucle+1;
         break;
         }

      case 0x3E00:  //RP_SpellListe
         {
         int cmp=9;
         moi.nbrspell=(pak_buffer[7]<<8)+pak_buffer[8];
         if(moi.nbrspell>0)
         {
         for(int i=0;i<=moi.nbrspell-1;i++)
            {
               //Send_sysmsg("Liste de sort trouvé");
               moi.listspell[i].idspell=(pak_buffer[0+cmp]<<8)+pak_buffer[1+cmp];
               moi.listspell[i].type_cible=pak_buffer[2+cmp];
               moi.listspell[i].mana=(pak_buffer[3+cmp]<<8)+pak_buffer[4+cmp];
               moi.listspell[i].icon=(pak_buffer[17+cmp]<<8)+pak_buffer[18+cmp];
               moi.listspell[i].lgtdes=(pak_buffer[19+cmp]<<8)+pak_buffer[20+cmp];
               cmp=cmp+moi.listspell[i].lgtdes;
               moi.listspell[i].lgtnom=(pak_buffer[21+cmp]<<8)+pak_buffer[22+cmp];

               char *temp3 = new char[moi.listspell[i].lgtnom+1];
               memcpy(temp3,pak_buffer+23+cmp,moi.listspell[i].lgtnom);
               temp3[moi.listspell[i].lgtnom] = '\0'; // fin de la chaine
               moi.listspell[i].nom=temp3;
               //Send_sysmsg(moi.listspell[i].nom);
               //Send_sysmsg("test");
               cmp=cmp+23+moi.listspell[i].lgtnom;
            }
         }
         break;
         }

      case 0x2700:  //RP_InfoSkills
         {
         int cmp=4;
         moi.nbrskill=(pak_buffer[2]<<8)+pak_buffer[3];
         if(moi.nbrskill>0)
         {
         for(int i=0;i<=moi.nbrskill-1;i++)
            {
               moi.listskill[i].idskill=(pak_buffer[0+cmp]<<8)+pak_buffer[1+cmp];
               moi.listskill[i].points=(pak_buffer[3+cmp]<<8)+pak_buffer[4+cmp];
               moi.listskill[i].boost=(pak_buffer[5+cmp]<<8)+pak_buffer[6+cmp];
               moi.listskill[i].lgtnom=(pak_buffer[7+cmp]<<8)+pak_buffer[8+cmp];

               char *temp4 = new char[moi.listskill[i].lgtnom+1];
               memcpy(temp4,pak_buffer+9+cmp,moi.listskill[i].lgtnom);
               temp4[moi.listskill[i].lgtnom] = '\0'; // fin de la chaine
               moi.listskill[i].nom=temp4;

               //Send_sysmsg(moi.listskill[i].nom);
               cmp=cmp+moi.listskill[i].lgtnom;

               moi.listskill[i].lgtdes=(pak_buffer[9+cmp]<<8)+pak_buffer[10+cmp];
               cmp=cmp+11+moi.listskill[i].lgtdes;
            }
         }
         break;
         }



   }
   }

   return pak_buffer;
}

//Concatener des chaines :
   buffer = (LPSTR) malloc(8 + 1);
   wsprintf(buffer, "%02u:%02u:%02u", sys_time.wHour, sys_time.wMinute, sys_time.wSecond);
   SYSMSG(buffer);


//Faire un systeme qui permet, lorsqu'on tappe .test "texte", d'afficher le texte.
void *fnProcessOut(unsigned char *pak_buffer, DWORD &taille, DWORD &param)
{
   param=PLUGIN_PAK_NOCHANGE;
   int offset=0,type;
   type=*(short *)pak_buffer;
   if (type==0x1B00)
      offset=13;
   if (type==0x1E00)
      offset=17;
   int special=100;
   if (offset)
      {
         if (!strnicmp((char *)&pak_buffer[offset],".test",5))
         {
         int taille_msg=(pak_buffer[offset-2]<<8)+pak_buffer[offset-1];
         char *message = (LPSTR) malloc(taille_msg-4); 
         memcpy(message, pak_buffer + offset+5, taille_msg-5);
         message[taille_msg-5] = '\0';
         Send_sysmsg(message);
         param=PLUGIN_PAK_DELETE;
         }
      }
   return pak_buffer;
}