[Release] Reading monster_ref.bmo

01/25/2017 15:08 Plastic#1
This is the structure for the monster_ref.bmo file. Everything marked with the comment "// not a monster attribute" means that it is ignored on the client. I believe it's only used on the server. You cannot change the text of "toolName" on the server monster_ref.bmo unless you modify the server executable, since it looks for "EOD Monster Ref" or it fails to load.

Code:
typedef struct
{
    char toolName[ 48 ];
    short version1;
    short version2;
    SYSTEMTIME systemTime;  // SYSTEMTIME is https://msdn.microsoft.com/en-us/library/windows/desktop/ms724950(v=vs.85).aspx
    char user_name[ 16 ];
    char com_name[ 20 ];
} MONSTERREF_HEADER;

typedef struct
{
    char mission;
    unsigned char length;
} MONSTERREFDATA;

typedef struct
{
    char dropLevel;
    char itemType; // not a monster attribute
    unsigned char itemMerge; // not a monster attribute
    short itemRank; // not a monster attribute
    int itemRate; // not a monster attribute
} MONSTERLOOPDATA;

typedef struct
{
    unsigned short level;
    unsigned char party;
    unsigned short scriptType; 

    char mission; // not a monster attribute

    unsigned char rank;
    
    char length; // not a monster attribute 
    char name[ length ]; // not a monster attribute 
    short size; // not a monster attribute 
    char adventTime; // not a monster attribute 
    char timeResult; // not a monster attribute 
    int hp; // not a monster attribute 
    short sp; // not a monster attribute 
    short stamina; // not a monster attribute 
    int upgradeExp; // not a monster attribute 
    char upgradeCount; // not a monster attribute 

    float speedWalk;
    float speedRun;

    float spSpeed; // not a monster attribute 
    float walkLength; // not a monster attribute 
    float runLength; // not a monster attribute 
    float spLength; // not a monster attribute 
    char activity; // not a monster attribute 
    short moonResist; // not a monster attribute 
    short sunResist; // not a monster attribute 
    short spiritResist; // not a monster attribute 
    short bodyResist; // not a monster attribute 
    char attribute; // not a monster attribute 
    char fAttribute; // not a monster attribute 
    short agility; // not a monster attribute 
    short agility1; // not a monster attribute 
    short defensePower; // not a monster attribute 
    short spellDefense; // skipped in client reading
    unsigned char attackClass; // not a monster attribute 
    unsigned char attackType; // not a monster attribute 
    short atkPowerMin; // not a monster attribute 
    short atkPowerMax;
    short attackSuccess; // not a monster attribute 
    short attackDelay; // not a monster attribute 

    short sUnk1;

    float attackAngle; // not a monster attribute 
    float attackRange; // not a monster attribute
    float attackArea; // not a monster attribute 
    short critCount; // not a monster attribute 
    short critEffect; // not a monster attribute 
    short rAtkPowerMin; // not a monster attribute 
    short rAtkPowerMax; // not a monster attribute 
    short rAtkSuccess; // not a monster attribute 
    short rAtkSuccess1; // not a monster attribute 
    short rAtkDelay; // not a monster attribute 
    float rAtkAngle; // not a monster attribute 
    float rAtkRange; // not a monster attribute 
    float rAtkArea; // not a monster attribute 
    short rCritCount; // not a monster attribute 
    short rCritEffect; // not a monster attribute 
    unsigned char attribute2; // not a monster attribute 
    int attributeAtk; // not a monster attribute 
    char specCondition1; // not a monster attribute 
    char specCount1; // not a monster attribute 
    short specSpellID1; // not a monster attribute 
    char specSpellLvl1; // not a monster attribute 
    short specSP1; // not a monster attribute 
    int specDelay1; // not a monster attribute 
    float specAngle1; // not a monster attribute 
    float specRange1; // not a monster attribute 
    float specArea1; // not a monster attribute
    char specCondition2; // not a monster attribute
    char specCount2; // not a monster attribute
    short specSpellID2; // not a monster attribute
    char specSpellLvl2; // not a monster attribute
    short specSP2; // not a monster attribute
    int specDelay2; // not a monster attribute
    float specAngle2; // not a monster attribute
    float specRange2; // not a monster attribute
    float specArea2; // not a monster attribute
    
    char cUnk[ 46 ]; // skip 46 unknown bytes, cuz client fseek's past
    
    char skillTitle1; // not a monster attribute
    short skillID1;
    char skillCondition1; // not a monster attribute
    char skillCount1; // not a monster attribute
    char skillTarget1; // not a monster attribute
    short skillSpellID1; // not a monster attribute
    char skillSpellLvl1; // not a monster attribute
    short skillSP1; // not a monster attribute
    int skillDelay1; // not a monster attribute
    unsigned char skillAngle1; // not a monster attribute
    float skillRange1; // not a monster attribute
    float skillArea1; // not a monster attribute
    short skillID2;
    char skillCondition2; // not a monster attribute
    char skillCount2; // not a monster attribute
    char skillTarget2; // not a monster attribute
    short skillSpellID2; // not a monster attribute
    char skillSpellLvl2; // not a monster attribute
    short skillSP2; // not a monster attribute
    int skillDelay2; // not a monster attribute
    unsigned char skillAngle2; // not a monster attribute
    float skillRange2; // not a monster attribute
    float skillArea2; // not a monster attribute
    unsigned short modelChange; // not a monster attribute
    char changeProb; // not a monster attribute
    short hpRegain; // not a monster attribute
    short spRegain; // not a monster attribute
    short staminaRegain; // not a monster attribute
    float normalScope; // not a monster attribute
    float chaseScope; // not a monster attribute
    char aiTarget; // not a monster attribute
    char aiItem; // not a monster attribute
    char aiAttack; // not a monster attribute
    char aiFamily; // not a monster attribute
    char aiEscape; // not a monster attribute
    char groupAttack; // not a monster attribute
    char aiBattle; // not a monster attribute
    short aiSiege; // not a monster attribute
    int tmp1; // not a monster attribute
    int tmp2; // not a monster attribute
    int tmp3; // not a monster attribute
    char expLevel;
    unsigned int returnExp; // not a monster attribute
    int returnSkillExp; // not a monster attribute
    char honorLevel; // not a monster attribute
    int returnHonor; // not a monster attribute
    int returnFame1; // not a monster attribute
    int returnFame2; // not a monster attribute
    int returnFame3; // not a monster attribute
    char goldLevel; // not a monster attribute
    unsigned int goldMin; // not a monster attribute
    unsigned int goldMax; // not a monster attribute
    int goldProb; // not a monster attribute

    MONSTERLOOPDATA monLoop[ 60 ]; // reads this data 60 times

    char attackProb; // not a monster attribute
    char keyType;
    short keyID;
    unsigned int respawnTimeMin; // not a monster attribute
    unsigned int respawnTimeMax; // not a monster attribute
    char monsterCount; // not a monster attribute
} MONSTERTABLE;

typedef struct
{
    unsigned short type_id;
    MONSTERTABLE monTable;
} MONSTRUCTURE;
Psuedocode to read the file data in:

Code:
FILE* pFile = nullptr;

fopen_s( pFile, "monster_ref.bmo", "rb" );

if ( !pFile )
    exit();

MONSTERREF_HEADER monHeader;

fread( monHeader.toolName, 48, 1, pFile );
.... (fread rest of header );

// read type_id in
MONSTRUCTURE monStruct;
while ( true )
{
    fread( monStruct.type_id, sizeof( monStruct.type_id ), 1, pFile );

    if ( type_id == 65535 ) // 65535 == end of file
        break;

    MONSTERTABLE monTable = &monStruct.monTable;
    fread( monTable.level, sizeof( unsigned short ), 1, pFile );
    .... ( fread rest of file );
}
Saving the output should be straight forward with this info. I've also attached a 010 Editor 7.0 template that you can use to edit the file if you are unwilling or incapable of writing a program to handle it yourself.

Have fun
02/03/2017 02:45 heineken0801#2
Hi Plastic. Many thanks for sharing!