• Welcome to Valhalla Legends Archive.
 

Statstring Parsing - c++ code

Started by iago, October 03, 2003, 03:47 PM

Previous topic - Next topic

iago

This isn't complete, but I got bored with it, so it's as complete as it's getting without somebody else contributing.  Here it is:

#include "ParseStatString.h"

#include <string>
#include <strstream>
using namespace std;

const char *Races[] =
   { "Unknown",
   "Amazon",
   "Sorceress",
   "Necromancer",
   "Paladin",
   "Barbarian",
   "Druid",
   "Assassin",
   "Unknown",
   "Unknown (Grey)",
   "Unknown (Grey)",
   "Diablo 1",
   "Diablo 1",
   "Diablo 1",
   "Starcraft Marine",
   "Brood War Medic",
   "Warcraft II Grunt",
   "Blizzard Rep",
   "Moderator",
   "Sysop",
   "Referee",
   "Chat",
   "Speaker" };



string ParseStatString::GetStatString(char *SS)
{
   string Product = SS;
   strstream Return;
   Product.resize(4);
   DWORD a, b, c, d, e, f, g, h, i, j;

   if(Product == "RHSS")
   {
      return "using Starcraft Shareware";
   }
   
   
   if(Product == "RATS" || Product == "PXES" || Product == "NB2W")
   {
      if(Product[0] == 'R')
         Return << "using Starcraft";
      else if(Product[0] == 'P')
         Return << "using Starcraft Broodwar";
      else
         Return << "using Warcraft II";

      if(sscanf(SS + 5, "%d %d %d %d %d %d %d %d %d", &a, &b, &c, &d, &e, &f, &g, &h, &i, &j) != 9)
      {
         Return << (BYTE)0;
         return Return.str();
      }
      else
      {
         if(d)
            Return << " spawn";
         if(a > 0)
         {
            Return << " (" << c << " wins, ladder: " << a << ", ladder max: " << f << ")";
         }
         else
         {
            Return << " (" << c << " wins)";
         }
         Return << (BYTE) 0;
         return Return.str();
      }
   }

   if(Product == "PX2D" || Product == "VD2D")
   {
      if(Product == "PX2D")
      {
         Return << "using Diablo 2: LoD";
      }
      else
      {
         Return << "using Diablo 2";
      }
      
      SS += 4;
      
      char *CharName = strchr(SS, ',');
      // Make sure there was a comma in it
      if(CharName == NULL)
      {
         Return << (BYTE) '\0';
         return Return.str();
      }
      // Set the last character in the realm to NULL
      *CharName = '\0';
      // Put the realm into a string
      string Realm = SS;
      // Go to the first character of the character name
      CharName++;
      
      // Get the first part of the stats section
      char *Stats = strchr(CharName, ',');
      // If no comma was found, return what we have
      if(Stats == NULL || strlen(Stats + 1) != 33)
      {
         Return << (BYTE) '\0';
         return Return.str();
      }
      // Set the end of CharName to NULL
      *Stats = '\0';
      Stats++;

      string Character = CharName;
      
      // Ok, we must be good, we will parse the rest of it now
      BYTE Level = Stats[25];
      BYTE Race = Stats[13];
      BOOL Hardcore = (BOOL)(Stats[26] & 4);
      BOOL Dead = (BOOL)(Stats[26] & 8);
      BYTE Helmet = Stats[2];
      BYTE Weapon = Stats[7];
      BYTE Shield = Stats[9];
   
      if(Race > 22)
      {
         Race = 0;
      }
      string strRace = Races[Race];

      string strHelm;
      switch(Helmet)
      {
      case 4:
      case 57:
         strHelm = "Cap";
         break;
      case 5:
      case 58:
         strHelm = "Skullcap";
         break;
      case 6:
      case 59:
         strHelm = "Helm";
         break;
      case 7:
      case 60:
         strHelm = "Fullhelm";
         break;
      case 8:
      case 61:
         strHelm = "Greathelm";
         break;
      case 10:
      case 63:
         strHelm = "Mask";
         break;
      case 40:
      case 82:
         strHelm = "Bonehelm";
         break;
      case 89:
         strHelm = "Fanged Helm";
         break;
      case 90:
         strHelm = "Warhelm";
         break;
      case 91:
         strHelm = "Winged Helm";
         break;
      default:
         strHelm = "No helm (";
         strHelm += (int) Helmet;
         strHelm += ")";
         break;
      }

      string strWeapon;

      switch(Weapon)
      {
      case 4:
         strWeapon = "Hatchet/Waraxe"; //
         break;
      case 5:
         strWeapon = "Axe"; //
         break;
      case 6:
         strWeapon = "Large Axe 6";
         break;
      case 7:
         strWeapon = "Large Axe 7";
         break;
      case 8:
         strWeapon = "Great Axe";
         break;
      case 9:
         strWeapon = "Wand 9";
         break;
      case 10:
         strWeapon = "Wand 10";
         break;
      case 11:
         strWeapon = "Wand 11";
         break;
      case 12:
         strWeapon = "Spiked Club"; //
         break;
      case 13:
         strWeapon = "Scepter"; //
         break;
      case 14:
         strWeapon = "Hammer";
         break;
      case 15:
         strWeapon = "Flail";
         break;
      case 16:
         strWeapon = "Maul";
         break;
      case 17:
         strWeapon = "Short Sword";
         break;
      case 18:
         strWeapon = "Scimitar/Saber"; //
         break;
      case 19:
         strWeapon = "Warsword"; //
         break;
      case 20:
         strWeapon = "Crystal Sword";
         break;
      case 21:
         strWeapon = "Sword 21";
         break;
      case 22:
         strWeapon = "Sword 22";
         break;
      case 23:
         strWeapon = "Sword 23";
         break;
      case 24:
         strWeapon = "Sword 24";
         break;
      case 25:
         strWeapon = "Dagger"; //
         break;
      case 26:
         strWeapon = "Dirk/Kris"; //
         break;
      case 27:
         strWeapon = "Unk 27";
         break;
      case 28:
         strWeapon = "Unk 28";
         break;
      case 29:
         strWeapon = "Unk 29";
         break;
      case 30:
         strWeapon = "Spear"; //
         break;
      case 31:
         strWeapon = "Trident";
         break;
      case 32:
         strWeapon = "Spetum";
         break;
      case 33:
         strWeapon = "Pike";
         break;
      case 34:
         strWeapon = "Bardiche/Halberd"; //
         break;
      case 35:
         strWeapon = "Sickle";
         break;
      case 36:
         strWeapon = "Poleaxe";
         break;
      case 37:
         strWeapon = "Staff 37";
         break;
      case 38:
         strWeapon = "Staff 38";
         break;
      case 39:
         strWeapon = "Staff 39";
         break;
      case 40:
         strWeapon = "Staff 40";
         break;
      case 49:
         strWeapon = "Unk 49";
         break;
      case 50:
         strWeapon = "Unk 50";
         break;
      case 56:
         strWeapon = "Unk 56";
         break;
      case 121:
         strWeapon = "Unk 121";
         break;
      case 122:
         strWeapon = "Unk 122";
         break;
      case 123:
         strWeapon = "Unk 123";
         break;
      case 124:
         strWeapon = "Unk 124";
         break;
      case 125:
         strWeapon = "Poison Potion";
         break;
      case 126:
         strWeapon = "Fulmigating Potion";
         break;
      case 127:
         strWeapon = "Potion 3";
         break;
      case 128:
         strWeapon = "Potion 4";
         break;
      case 129:
         strWeapon = "Potion 5";
         break;
      default:
         strWeapon = "No weapon (";
         strWeapon += (int)Weapon;
         strWeapon += ")";
      }

      string strShield;

      switch(Shield)
      {
      case 79:
         strShield = "Small shield";
         break;
      case 80:
         strShield = "Buckler";
         break;
      case 81:
         strShield = "Kite Shield";
         break;
      case 82:
         strShield = "Tower Shield";
         break;
      case 84:
         strShield = "Bone Shield";
         break;
      case 85:
         strShield = "Spiked Shield";
         break;
      case 92:
         strShield = "Rondache";
         break;
      case 94:
         strShield = "Crown Shield";
         break;
      default:
         strShield = "No Shield (";
         strShield += (int)Shield;
         strShield += ")";
      }

      // Now that we have all the pieces, build the packet
      Return
         << " ("
         << Character
         << ", a level "
         << (int)Level
         << " "
         << Races[Race]
         << " using a "
         << strWeapon
         << ", a "
         << strHelm
         << ", and a "
         << strShield;

      if(Hardcore)
         Return << ", Hardcore";
      if(Dead)
         Return << ", Dead";

      Return << ")" << (BYTE) '\0';

      return Return.str();
   }

   if(Product == "LTRD" || Product == "RHSD")
   {
      if(Product == "LTRD")
         Return << "using Diablo";
      else
         Return << "using Diablo Shareware";

      if(sscanf(SS + 5, "%d %d %d %d %d %d %d %d %d", &a, &b, &c, &d, &e, &f, &g, &h, &i, &j) != 9)
      {
         Return << (BYTE) '\0';
         return Return.str();
      }
      
      Return << ", a Level " << a;
      if(b == 0)
      {
         Return << " warrior";
      }
      else if(b == 1)
      {
         Return << " rogue";
      }
      else if(b == 2)
      {
         Return << " sorcerer";
      }
      
      Return << " with " << c << " dots, " << d << " strength, " << e << " magic, " << f << " dexterity, " << g << " vitality, and " << h << " gold" << (BYTE) '\0';
      return Return.str();
   }

   if(Product == "TAHC")
   {
      Return << "using a Chat Bot" << (BYTE) '\0';
   }

   if(Product == "3RAW")
   {
      Return << "using Warcraft 3" << (BYTE) 0;
      return Return.str();
   }


         

   Return << "with an unrecognized statstring: " << SS << '\0';
   return Return.str();
}
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


iago

#1
hmm, I guess I should also post the .h file:


#ifndef PARSESTATSTRING_H
#define PARSESTATSTRING_H

#include <windows.h>
#include <iostream>
using namespace std;

class ParseStatString
{
public:
   ParseStatString();
   static string GetStatString(char *SS);

};


#endif
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


UserLoser

#2
 ;D Thanks a ton - now for me to change it to VB :P

iago

lol, no.

It's not terribly complicated code, for the most part.. shouldn't be horribly difficult to translate :)
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


K

#4
Just as a really picky sidenote, you shouldn't use

using namespace std;


in a header file, since it will e(a?)ffect all the source files that include it, which can cause some undesired naming conflicts.  I'll usually write out the fully qualified name (std::string) in the header, and then add using declarations in the source file.

But other than that teeny point, nicely done.

Banana fanna fo fanna

Wow...someone actually uses the std c++ string class!?

K

#6
Quote from: St0rm.iD on October 03, 2003, 07:08 PM
Wow...someone actually uses the std c++ string class!?

The real question is why anyone wouldn't use it.  Goodbye dealing with null terminator; goodbye strcmp, strcat, strcpy; goodbye buffer overflows; goodbye possible memory leaks...

Eibro

If i'm not mistaken, std::strstream is deprecated. You should use header file sstream instead. std::ostringstream/std::istringstream/std::stringstream should offer the same functionality.
Eibro of Yeti Lovers.

Banana fanna fo fanna

K, I know the benefits, but no one uses it.

Kp

Quote from: K on October 03, 2003, 07:19 PMThe real question is why anyone wouldn't use it.
When was the last time you saw a system call that took or returned an std::string?  STL may be nice for intraprocess work, but it can be a nuisance when you're regularly passing things into and out of the OS.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

iago

We use std::string and strstream in school for assignments, so that's why I use it; a lot of people use is, especially at school.  And Kp is right - but I'm not using any API calls, so life is good.

And K - I've never had a problem with setting that namespace in .h files, but that's the only namespace I ever use.  
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*