Jump to content

EterGroupParser - Script your txt / msm


Recommended Posts

  • Honorable Member

This is the hidden content, please
 (
This is the hidden content, please
)
I've created a script that processes Eter Group files. It can load, save, edit, repair, mass-update, and more.
Right now I'm using it for automatically repairing mob_drop_item.txt, and mass-updating the drops at once.

It also preserves the comments made with '#' in their correct place, except for the comments in the root below other Groups. (they'll be moved on top)

The tree of a loaded group file will be like:

ScriptType: ['RaceDataScript']
BaseModelFileName: "d:/ymir work/pc/warrior/warrior_novice.GR2"
Group CorDraconis(Mystical):
    Vnum: [51506]
    1: [115000, 1, 1]
    2: [125000, 1, 1]
    3: [135000, 1, 1]
    4: [145000, 1, 1]
    5: [155000, 1, 1]
    6: [165000, 1, 1]

Group BodyChest:
    Vnum: [71203]
    1: [50401, 1, 1]
    2: [50402, 1, 1]
    3: [50403, 1, 1]
    4: [50404, 1, 1]
    5: [50405, 1, 1]

Group MentalChest:
    Vnum: [71205]
    1: [50416, 1, 1]
    2: [50417, 1, 1]
    3: [50418, 1, 1]
    4: [50419, 1, 1]
    5: [50420, 1, 1]

Group Cung_Mok:
    type: ['drop']
    mob: [151]
    1: [71151, 1, 100]
    2: [71151, 1, 100]
    3: [71151, 1, 100]
    4: [71151, 1, 100]
    5: [71151, 1, 100]
    6: [71299, 1, 50]
    7: [71740, 2, 50]
    8: [1, 20000, 50]
    9: [1, 30000, 30]

Group ApplyNumSettings:
    Group Default:
        basis: [1, 1, 1, 2, 2, 3]
        add_min: [0, 0, 0, 0, 0, 0]
        add_max: [0, 1, 2, 2, 3, 3]

    Group NotSoDefault:
        basis: [1, 2, 3, 4, 5]
        add_min: [5, 4, 3, 2, 1]
        add_max: [11, 3, 5, 7, 22]

    Group MixedTypes:
        1: ['MAX_SP', 500]
        2: ['RESIST_WIND', 10]
        3: ['ENCHANT_WIND', 10]


Group HairData:
    PathName: "d:/ymir Work/pc/warrior/"
    HairDataCount: [999]
    Group HairData00:
        HairIndex: [0]
        Model: "hair/hair_1_1.gr2"
        SourceSkin: "hair/hair_1_1.dds"
        TargetSkin: "warrior_hair_01.dds"

    Group HairData01:
        HairIndex: [1]
        Model: "hair/hair_1_1.gr2"
        SourceSkin: "hair/hair_1_1.dds"
        TargetSkin: "warrior_hair_01_white.dds"

    Group HairData02:
        HairIndex: [2]
        Model: "hair/hair_1_1.gr2"
        SourceSkin: "hair/hair_1_1.dds"
        TargetSkin: "warrior_hair_01_gold.dds"

Examples:

    if True: # load, print, and save
        egr = EterGroupReader()
        egr.LoadFromFile('sample.txt')
        egr.PrintTree()
        egr.SaveToFile('sample-out.txt')

    if True: # find node and print it
        egr = EterGroupReader()
        egr.LoadFromFile('sample.txt')
        node = egr.FindNode("ApplyNumSettings", "Default", "basis")
        if node:
            print("node {} found with value {}".format(node.key, node.value))

    if True: # find node and edit it
        egr = EterGroupReader()
        egr.LoadFromFile('sample.txt')
        node = egr.FindNode("ApplyNumSettings", "Default", "basis")
        if node:
            node.value = [11, 22, 33, 44, 55, 66]
        egr.SaveToFile('sample-out.txt')

    if True: # iter all groups and sub groups
        egr = EterGroupReader()
        egr.LoadFromFile('sample.txt')

        # Create an instance of the iterator
        group_iterator = EterGroupIterator(egr, skipRoot=True)

        # Iterate over all groups using a lambda or function
        for group in group_iterator:
            print(f"Group Name: {group.name}")

    if True: # load mob_drop_item and print only the metins
        egr = MobDropItemHelper()
        egr.LoadFromFile('mob_drop_item.txt')
        for group in egr.GetGroupsOfMetins():
            egr.PrintTree(group)
            print("HIGHEST", GetGroupHighestIndex(group))
        egr.SaveToFile('mob_drop_item-out.txt')

    if True: # load mob_drop_item and add a red potion in the metin drops
        egr = MobDropItemHelper()
        egr.LoadFromFile('mob_drop_item.txt')
        for group in egr.GetGroupsOfMetinsAndDrop():
            egr.AddIndexElement(group, [27001, 1, 6.6])
            egr.PrintTree(group)
        egr.SaveToFile('mob_drop_item-out.txt')

    if True: # load mob_drop_item and add a red potion in vnum list
        egr = MobDropItemHelper()
        egr.LoadFromFile('mob_drop_item.txt')
        for group in egr.GetGroupsOf(lambda group: IsVnumInListGroup(group, [101, 105, 1059])):
            egr.AddIndexElement(group, [27001, 1, 6.6])
            egr.PrintTree(group)
        egr.SaveToFile('mob_drop_item-out.txt')

    if True: # load mob_drop_item and check for errors
        egr = MobDropItemHelper()
        egr.LoadFromFile('mob_drop_item.txt')
        for group in egr.GetGroups():
            valid, found = CheckValidContinuousGroupIndex(group)
            if not valid:
                egr.PrintTree(group)
                print(f"NOT VALID: Error at group '{group.name}' index {found}")
                break
        egr.SaveToFile('mob_drop_item-out.txt')

    if True: # load mob_drop_item and repair for index errors
        egr = MobDropItemHelper()
        egr.LoadFromFile('mob_drop_item.txt')
        for group in egr.GetGroups():
            RepairContinuousGroupIndex(group)
        egr.SaveToFile('mob_drop_item-out.txt')

 

If you have any suggestions, comment the topic.

 

  • Metin2 Dev 40
  • Eyes 1
  • Good 8
  • Love 1
  • Love 12
Link to comment
Share on other sites

  • Honorable Member

Updated with the following changes:
 

1)

"""
Added support for #--# and the relative column aliases
"""

        egr = EterGroupReader()
        egr.LoadFromFile('sample.txt')
        node = egr.FindNode("ApplyNumSettings", "Default", "basis")
        if node:
            print("GRADE_NORMAL", "has index", node.GetAliasIndex("GRADE_NORMAL"), "and value", node.GetAliasValue("GRADE_NORMAL"))
            print("GRADE_BRILLIANT", "has index", node.GetAliasIndex("GRADE_BRILLIANT"), "and value", node.GetAliasValue("GRADE_BRILLIANT"))
            print("GRADE_RARE", "has index", node.GetAliasIndex("GRADE_RARE"), "and value", node.GetAliasValue("GRADE_RARE"))
            print("GRADE_ANCIENT", "has index", node.GetAliasIndex("GRADE_ANCIENT"), "and value", node.GetAliasValue("GRADE_ANCIENT"))
            print("GRADE_LEGENDARY", "has index", node.GetAliasIndex("GRADE_LEGENDARY"), "and value", node.GetAliasValue("GRADE_LEGENDARY"))
            print("GRADE_MYTH", "has index", node.GetAliasIndex("GRADE_MYTH"), "and value", node.GetAliasValue("GRADE_MYTH"))
        egr.SaveToFile('sample-out.txt')


Result:
    GRADE_NORMAL has index 0 and value 1
	GRADE_BRILLIANT has index 1 and value 1
	GRADE_RARE has index 2 and value 1
	GRADE_ANCIENT has index 3 and value 2
	GRADE_LEGENDARY has index 4 and value 2
	GRADE_MYTH has index 5 and value 3
    
    
From .txt:
Group	ApplyNumSettings
{
	Group	Default
	{
		#--#	GRADE_NORMAL	GRADE_BRILLIANT	GRADE_RARE	GRADE_ANCIENT	GRADE_LEGENDARY	GRADE_MYTH
		basis	1	1	1	2	2	3
		add_min	0	0	0	0	0	0
		add_max	0	1	2	2	3	3
	}
}

 

2)

"""
Added find or create group def
"""
        egr = MobDropItemHelper()
        egr.LoadFromFile('mob_drop_item.txt')
        group = FindOrCreateMobDropGroup(egr, 691, "limit")
        egr.AddIndexElement(group, [27001, 11, 6.12])
        egr.AddIndexElement(group, [27002, 22, 12.34])
        egr.AddIndexElement(group, [27003, 33, 18.56])
        egr.PrintTree(group)
        egr.SaveToFile('mob_drop_item-out.txt')

        
Result:
Group Mob691TypeLimit:
    type: ['limit']
    mob: [691]
    1: [27001, 11, 6.12]
    2: [27002, 22, 12.34]
    3: [27003, 33, 18.56]

3)

"""
Added some functions to edit the MSM files
"""
    	#load a .msm and replace a specific shape from <old> to <new>
        egr = RaceDataHelper()
        egr.LoadFromFile('assassin_m.msm')
        egr.ReplaceShapeIndexValue(44114, 44115)
        egr.SaveToFile('assassin_m-out.msm')

 

  • Metin2 Dev 1
  • Love 5
Link to comment
Share on other sites

  • 4 months later...

Announcements



×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.