From The Mana World

This is some notes on the save formats of TMWA. It is not intended to authorative, but rather a porting tool.

It does NOT document the config formats - which includes login/save/gm_account.txt - or the script formats.

General

Save files generally consist of a number of tab separated fields, each of which may consist of a number of space and/or comma-separated fields.

Any line starting with //, or being empty, is usually ignored. But, any line not matching for format correctly is also usually ignored.

If there are any C0 control characters, funny stuff might happen.

integer

All integers stored at this level are in base 10.

/0|-?[1-9][0-9]*/

bool

A bool is just an integer that is expected to have the value 0 or 1 only.

string

A string is a sequence of non-control characters.

word

A word is a string containing no spaces.

char

a char is maybe a word of length 1. Bad things would happen if it were length 0 instead.

item

An item - which is usually in a space-separated list, which is itself between tabs - consists of:

Comma-separated fields:

  1. int id
  2. int nameid
  3. int amount
  4. int equip
  5. int identify
  6. int refine
  7. int attribute
  8. int card0
  9. int card1
  10. int card2
  11. int card3
  12. optional int borken

Add new common types here

login/save/account.txt

The standard 12 or 13 tab separated fields form, followed by a final "special" field:

  1. int account_id
  2. string userid
  3. string pass
  4. string lastlogin
  5. char sex
  6. int logincount
  7. int state
  8. string email
  9. string error_message
  10. int connect_until_time
  11. string last_ip
  12. string memo
  13. optional int ban_until_time
  14. account_reg2 variables (##) (there may be from 0 to 16 of these, separated by spaces)
    1. variable entries - the key and value are comma separated.
      1. string-nocomma key
      2. int value

There is an older version with 5-7 fields, plus the variables again:

  1. int account_id
  2. string userid
  3. string pass
  4. string lastlogin
  5. char sex
  6. optional int logincount
  7. optional int state
  8. account_reg2 variables again ...

Finally, there is a sentinel:

  1. int account_id
  2. literal string "%newid%"

char/save/athena.txt

It may be a sentinel:

  1. int char_id_count
  2. literal string %newid%

Or it may contain data:

  1. int char_id
  2. comma-separated:
    1. int account_id
    2. int char_num
  3. string name
  4. comma-separated:
    1. int class
    2. int base_level
    3. int job_level
  5. comma-separated:
    1. int base_exp
    2. int job_exp
    3. int zeny
  6. comma-separated:
    1. int hp
    2. int max_hp
    3. int sp
    4. int max_sp
  7. comma-separated:
    1. int str
    2. int agi
    3. int vit
    4. int int
    5. int dex
    6. int luk
  8. comma-separated:
    1. int status_point
    2. int skill_point
  9. comma-separated:
    1. int option
    2. int karma
    3. int manner
  10. comma-separated:
    1. int party_id
    2. int guild_id
    3. optional int pet_id
  11. comma-separated:
    1. int hair (style)
    2. int hair_color
    3. int clothes_color
  12. comma-separated:
    1. int weapon
    2. int shield
    3. int head_top (hat)
    4. int head_mid (chest/torso)
    5. int head_bottom (legs)
  13. comma-separated:
    1. string last_point.mapname,
    2. int last_point.x
    3. int last_point.y
  14. comma-separated:
    1. string save_point.mapname,
    2. int save_point.x
    3. int save_point.y
    4. optional int partner_id
  15. 0 to ??? unseparated (and thus broken for maps with numerical names):
    1. memo.mapname
    2. memo.x
    3. memo.y
  16. 0 to 100 space-separated inventory items
  17. 0 to 100 space-separated cart items
  18. 0 to 450 space-separated:
    1. int skill_id
    2. int skill_flags << 16 | skill_level
  19. 0 to GLOBAL_REG_NUM space-separated:
    1. string key
    2. int value

char/save/accreg.txt

tab separated:

  1. int account_id
  2. 0 to 16 space separated:
    1. comma-separated:
      1. string key
      2. int value

char/save/storage.txt

tab-separated:

  1. comma-separated:
    1. int account_id
    2. int storage_amount
  2. 0 to 300 space separated:
    1. item (however the 'broken' field does not work properly)

char/save/party.txt

It may be a sentinel:

  1. int party_newid
  2. literal string %newid%

It may be a party entry:

  1. int party_id
  2. string name
  3. comma separated:
    1. bool exp
    2. bool item

immediately followed by 0 to 12 of *tab* separated (hmph):

  1. comma-separated
    1. int account_id
    2. int leader
  2. string name

map/save/mapreg.txt

This file does NOT do comment checking. However, it does still check the format and skip if it fails.

Each line is tab separated:

  1. comma-separated...
    1. string varname
    2. optional int arrayindex
  2. string/int value, depending on whether varname ends with a $

Add new sections here