Reading from Character files (.chr)

Initiate Mage
Joined
Nov 30, 2019
Messages
2
Reaction score
0
Hi all PT devs

Have anyone had success in converting or attempted to read all data from raw character files (.chr) into other readable format such as database tables?

If not, before I try and do this task is there any pro / con of using another source to store the data (such as MSQL) instead of .chr files?

I can see one obvious pro. It allows you do create a script to modify or remove items etc in player's warehouse and character file (inventory). And look for items that were edited (hack)
 
Last edited:
Okay, I'm getting somewhere with this..

I was able to read in items stored in .chr. However if I try and modify the stats of items (patching) it won't work in the end (item disappears). I think it's because the checksum values no longer reflect the newly modified data.

Item struct has these two DWORD membrs
- iChk1
- iChk2

Does anyone know how these two checksums are calculated / generated in the first place? All checksums have certain pattern in how they were generated. I'll look around, but perhaps someone here already knows the answer to this one.\



Nevermind - it's funny how after you ask for help, you end up finding the answer to your own question shortly later....!
 
I do have a program that reads all item data in the char file and spits it out into a sql database.
SUPER easy then for hacked/modified item detection.

Made by Gregoo, source included.

 
I do have a program that reads all item data in the char file and spits it out into a sql database.
SUPER easy then for hacked/modified item detection.

Made by Gregoo, source included.

The post is quite old and the link seems dead. Is this still available? Could you reshare it please?
 
Since it's '.chr', I believe it comes from fPT. The file structure was modified to fit the kPT 2014 game version that I've used.

hope it helps

C++:
struct SocketItem
{
    ESocketType     eSocketType;
    EGemType        eGemType;
    EGemItem        eGemItem;
};

struct SpecItemData
{
    float                                    fSpecAbsorbRating;
    int                                        iSpecDefenseRating;
    float                                    fSpecMovementSpeed;
    float                                    fSpecBlockRating;
    int                                        iSpecAttackSpeed;
    int                                        iSpecCritical;
    int                                        iSpecAttackRange;
    float                                    fSpecMagicMastery;
    short                                    saSpecElementalDef[8];
    short                                    saSpecElementalAtkDiv[8];
    int                                        iSpecAddMPDiv;
    int                                        iSpecAddHPDiv;
    int                                        iSpecAttackRatingDiv;
    short                                    iSpecAttackPowerDivMin;
    short                                    iSpecAttackPowerDiv;
    float                                    fSpecMPRegen;
    float                                    fSpecHPRegen;
    float                                    fSpecSPRegen;
    int                                        iSpecEvade;

    short                                    sSpecPenetration;
    short                                    sSpecHPPotionEfficience;
    short                                    sSpecMPPotionEfficience;
    short                                    sSpecSPPotionEfficience;


    int                                        iPadding99[29];
};

class ItemID
{
public:
    ItemID() {};
    ItemID( int i ) { *(int *)(this) = i; }

    char                                    iIDHigh;    //always zero
    char                                    iIDLow;        //++ counter
    short                                    sItemType;

    inline unsigned int                        ToInt() { return *(unsigned int *)(this); }
    inline unsigned int                        & ToRefInt() { return *(unsigned int *)(this); }
    inline EItemID                            ToItemID() { return *(EItemID*)(this); }
    inline EItemType                        ToItemType() { return (EItemType)(*(unsigned int *)(this) & 0xFFFF0000); }
    inline EItemBase                        ToItemBase() { return (EItemBase)(*(unsigned int *)(this) & 0xFF000000); }

    inline void                                SetItemID( EItemID iItemID ) { *(EItemID*)this = iItemID; }

    static inline ItemID                    * ToItemID( EItemID * i ) { return (ItemID *)i; }
};

struct Item
{
    //Attributes
    DWORD                                    dwSize;
    ITEMCHECKSUM                            iChk1;
    DWORD                                    dwVersion;
    DWORD                                    dwTime;
    ITEMCHECKSUM                            iChk2;

    //Statistics
    CurMax                                    sIntegrity;
    ItemID                                    sItemID;
    char                                    szItemName[32];
    int                                        iWeight;
    int                                        iSalePrice;
    int                                        iIndex;
    int                                        iPotionCount;
    short                                    saElementalDef[8];
    int                                        iSight;
    int                                        iChecksum3;
    MinMax                                    sDamage;
    int                                        iAttackRange;
    int                                        iAttackSpeed;
    int                                        iAttackRating;
    int                                        iCritical;
    float                                    fAbsorbRating;
    int                                        iDefenseRating;
    float                                    fBlockRating;
    float                                    fMovementSpeed;
    int                                        iPotionStorage;
    float                                    fMagicMastery;
    float                                    fMPRegen;
    float                                    fHPRegen;
    float                                    fSPRegen;
    float                                    fAddHP;
    float                                    fAddMP;
    float                                    fAddSP;
    int                                        iLevel;
    int                                        iStrength;
    int                                        iSpirit;
    int                                        iTalent;
    int                                        iAgility;
    int                                        iHealth;
    MinMax                                    sMPRecovery;
    MinMax                                    sHPRecovery;
    MinMax                                    sSPRecovery;
    int                                        iGold;
        
    BOOL                                    bCanNotUse;

    DWORD                                    iBackupKey;
    DWORD                                    iBackupChk;

    short                                    iScaleBlink[2];
    int                                        iItemUniqueID;
    short                                    sEffectBlink[2];
    short                                    sEffectColor[4];
    BOOL                                    bEnableEffect;

    int                                        eSpecialization;
    SpecItemData                            sSpecData;

    EItemCraftType                            eCraftType;
    int                                        eMixEffect;
    union
    {
        USHORT                                sAgeLevel;
        USHORT                                sMixID;
    };
    USHORT                                    bMaturing;
    UCurMax                                    sMatureBar;
    
    short                                    saCraftProtection[2];

    short                                    sSpecialItemType[2];

    DWORD                                    tTime;
    SocketItem                                sSocketData[2];

    BYTE                                    bCostumeItem;
    BYTE                                    bEvade;
    BYTE                                    bLockedItemType;
    char                                    cPadding[11];

    CurMax                                    sQuestMonsters;

    EMixTypeName                            eMixTypeName;
    BOOL                                    bPerfectItem;

    int                                        iPadding666;
};


struct RecordItem
{
    int            iItemCount;

    Point2D        sItemPosition;
    int            iItemPosition;

    Item    sItem;
};

struct RecordSkill
{
    BYTE        baSkillPoints[20];
    WORD        waSkillMastery[20];
    BYTE        baShortKey[20];
    WORD        waSelectSkill[2];
};


struct CharacterData
{
    char                  szName[32];
    union
    {
        struct
        {
            char          szBodyModel[64];
            char          szHeadModel[64];
        } Player;
        struct
        {
            char          szBodyModel[64];
            char          szHeadModel[60];
            int              iMonsterID;
        } Monster;
        struct
        {
            char          szBodyModel[64];
            char          szHeadModel[60];
            int              iNPCID;
        } NPC;
        struct
        {
            char          szBodyModel[65];
            char          szOwnerName[63];
        } Pet;
        struct
        {
            char          szBodyModel[64];
            char          szHeadModel[4];
            char          szCharacterNameOwner[56];
            int              iNPCID;
        } XmasTree;
    };
    unsigned int          iID;                    //0xA0
    unsigned int          iClanID;                //0xA4
    ECharacterType          iType;                //0xA8
    int                      iShadowSize;            //0xAC
    EMonsterEffectID      iMonsterEffectID;        //0xB0
    ECharacterClass          iClass;                //0xB4
    int                      iLevel;                //0xB8
    int                      iStrength;            //0xBC
    int                      iSpirit;                //0xC0
    int                      iTalent;                //0xC4
    int                      iAgility;                //0xC8
    int                      iHealth;                //0xCC
    int                      iAccuracy;            //0xD0
    int                      iAttackRating;        //0xD4
    int                      iMinDamage;            //0xD8
    int                      iMaxDamage;            //0xDC
    int                      iAttackSpeed;            //0xE0
    int                      iAttackRange;            //0xE4
    int                      iCritical;            //0xE8
    int                      iDefenseRating;        //0xEC
    int                      iBlockRating;            //0xF0
    int                      iAbsorbRating;        //0xF4
    int                      iMovementSpeed;        //0xF8
    union
    {
        int                  iSight;                //0xFC - Does get used by players it seems
        int                  iNPCId;                //0xE8 //npc ids for normal npc units
    };
    CurMax                  sWeight;                //0x100
    short                  sElementalDef[8];        //0x104    (index 3 = ice, 4 = poison)
    short                  sElementalAtk[8];        //0x114
    CurMax                  sHP;                    //0x124
    CurMax                  sMP;                    //0x128
    CurMax                  sSP;                    //0x12C
    float                  fHPRegen;                //0x130
    float                  fMPRegen;                //0x134
    float                  fSPRegen;                //0x138
    unsigned int          iCurrentExpLow;        //0x13C
    int                      iOwnerID;                //0x140
    int                      iGold;                //0x144
    union
    {
        struct UnitInfo    * psUnitInfo;            //0x148
        int                 sBSAL;                //0x148
    };
    EMonsterType          iMonsterType;            //0x14C
    int                      iStatPoints;            //0x150
    char                  cNewLoad;                //0x154
    char                  cUnknown389103821;    //0x155
    char                  cUnknown358923102;    //0x156
    char                  cUnknown869023021;    //0x157
    MinMax                  sViewBoxZoom;            //0x158

    CurMax                  sHPBlocks;
    int                      iaPadding03;            //0x15C
    int                      iMPType;                //0x164
    BOOL                  bSPType;                //0x168

    int                      iUnknown12;            //0x16C

    DWORD                  dwChecksum;            //0x170
    ECharacterRank          iRank;                //0x174
    EClassFlag              iFlag;                //0x178
    short                  sWarpHomeTown;        //0x17C
    short                  sUnused23841212352;    //0x17E
    short                  sGlow;                //0x180
    short                  sSize;                //0x182
    unsigned int          iCurrentExpHigh;        //0x184
    BOOL                  bCustomHead;            //0x188

    BOOL                  bExclusiveBoss;
    BOOL                  bGrandFuryBoss;

    BYTE                sLevelAgeArmor;
    BYTE                baUnk004848[3];
    int                      iaUnused[13];
    short                  saUnused;
    short                  bResetStatistics;        //Used with Event Girl

}; //Size = 0x01D0

struct QuestCharacterSave
{
    WORD                waQuestID[2];

    union
    {
        DWORD                dwaData[7];
        char                szBuffer[0x1C];
    };
};

#define    LAST_QUEST_MAX        32

struct LastQuestSave
{
    WORD                waQuestID[LAST_QUEST_MAX];

    UINT                iCount;
};

#define MAX_POTION_SAVE_SLOTS    3
#define MAX_POTION_SAVE_COUNT    4

struct CharacterSave
{
    DWORD                dwHeader;

    EMapID                iMapID;

    int                    iCameraMode;
    int                    iLastPositionX;
    int                    iLastPositionZ;
    int                    iLastGold;

    DWORD                dwChecksum;

    RecordSkill            sSkillInfo;

    int                    iSaveTime;

    int                    iPadding69[2];

    short                bShowInitialPet;
    short                sElementPet;

    short                sPotionUpdate[2];
    short                sPotionCount[MAX_POTION_SAVE_SLOTS][MAX_POTION_SAVE_COUNT];
    WORD                wForceOrbUsing[2];

    UINT                iQuestFlag;

    int                    iShortKeyDefaultSkill;

    int                    iBlessCastleTax;
    int                    iBlessCastleClanID;

    int                    iElementaryQuestFlag;

    int                    iPadding72[12];

    int                    iTotalSubExp;
    int                    iTotalGold;
    int                    iTotalExp;    

    char                szAccountName[32];

    QuestCharacterSave    sQuestInfo;
    LastQuestSave        sLastQuestInfo;

    int                    iPadding08[35];
};


struct DropItemData
{
    int                                        iItemID;
    int                                        iChk1;
    DWORD                                    iChk2;
};

struct    PacketCharacterRecordData : Packet
{
    char            szHeader[8];

    CharacterData    sCharacterData;
    CharacterSave    sCharacterSaveData;

    DropItemData    saDropItemData[64];
    UINT            iDropItemCount;

    UINT            iItemCount;
    int                iItemSubStart;

    int                iDataSize;
    BYTE            baData[sizeof(RecordItem) * MAX_RECORD_ITEMS]; //<-- Items 
};
 
Back