Jump to content

Recommended Posts

  • Premium

Hey,

Here is my script for generating property for Trees, Buildings, Effects and Dungeon Blocks to make work more efficent.

- crc32 as ObjectID (same as in WE)

- skip LOD file (.gr2)

- adjustable shadow output (Buildings)

- auto .mdatr attachment (Collisions for *.gr2)

Script:

Spoiler

import os
import glob
import binascii

prb = "gr2 >> object"
prd = "gr2 >> dungeon block"
prt = "spt >> tree"
pre = "mse >> effect"
bshadow = ''
filetype = [prb, prd, prt, pre]
filename = []
filepath = []
crc32 = []
filecount = 0
currentfile = 0
count = 0

def clear():
    os.system('cls')


def getcrc32(f):
    fo = open(f, 'rb').read()
    return binascii.crc32(fo) % (1 << 32)


def properties(fileext, propertyext, propetytype):
    global currentfile, filecount, count
   
    for srcfn in glob.glob('*%s' % fileext):
        if '_lod_0' in srcfn:  # skip LOD files
            pass
        else:
            filename.append(srcfn)
            filepath.append((os.getcwd() + '\%s' % srcfn).replace('\\', '/').lower())
            filecount += 1

    for i in range(0, len(filename)):
        prop = open(filename[i][:-4] + propertyext, 'w')
        prop.write('YPRT\n')
        crc32.append(getcrc32(filename[i]))
        prop.write(str(crc32[i]) + '\n')
        if propertyext == '.prb':
            prop.write('buildingfile\t\t"%s"' % filepath[i].lower())
            if os.path.exists(filename[i][:-4] + '.mdatr'):
                prop.write('\nisattributedata\t\t"0"')  # include .mdatr
        if propertyext == '.prd':
            prop.write('dungeonblockfile\t\t"%s"' % filepath[i].lower())
        if propertyext == '.prt':
            prop.write('treefile\t\t"%s"' % filepath[i].lower())
        if propertyext == '.pre':
            prop.write('effectfile\t\t"%s"' % filepath[i].lower())
        prop.write('\npropertyname\t\t"%s"\n' % filename[i][:-4])
        prop.write('propertytype\t\t"%s"\n' % propetytype)
        if propertyext == '.prb' and bshadow == 'T':
            prop.write('shadowflag\t\t"1"\n')  # include shadow
        if propertyext == '.prt':
            prop.write('treesize\t\t"1000.000000"\n')
            prop.write('treevariance\t\t"0.000000"')

        print "(%d/%d) %s | crc32: %d" % (currentfile + 1, filecount, filename[i], crc32[i])
        currentfile += 1
        count += 1

      
def option(ext):
    global bshadow

    if ext == prb:
        outputshadow = raw_input("Include shadows? (T/N): ")
        if outputshadow == 't' or outputshadow == 'T':
            bshadow += 'T'
        properties('.gr2', '.prb', 'Building')
    if ext == prd:
        properties('.gr2', '.prd', 'DungeonBlock')
    if ext == prt:
        properties('.spt', '.prt', 'Tree')
    if ext == pre:
        properties('.mse', '.pre', 'Effect')


def menu():
    print "1) ", prb
    print "2) ", prd
    print "3) ", prt
    print "4) ", pre
    select = raw_input("Choose option: ")
    if 5 > int(select) > 0:
        clear()
        print "You have chosen: ", filetype[int(select) - 1]
        option(filetype[int(select) - 1])
    else:
        clear()
        menu()


menu()
print "Generated", count
raw_input("Press any key to exit")

Video:

222557xYQMvJt.gif

 

How to use:

1. Install the newest python 2.7.x

2. Paste script into text editor and save with .py extension

3. Put that script in directory with objects

4. Right click on script -> open as -> python.exe

 

 

  • Metin2 Dev 10
  • Love 1
  • Love 17
Link to comment
https://metin2.dev/topic/11267-batch-property-generator/
Share on other sites

  • 6 months later...
  • 3 months later...
  • 3 weeks later...
  • 5 months later...
  • 4 years later...
  • 2 years later...

thanks @ Domniq for the code.

I upgraded it for Python 3.x and added a function that creates a .txt with the last used propertyID so it doesn't appear multiple times when generating.

 

Spoiler
# -*- coding: utf-8 -*-
import os
import glob
import binascii

prb = "gr2 >> object"
prd = "gr2 >> dungeon block"
prt = "spt >> tree"
pre = "mse >> effect"
bshadow = ''
filetype = [prb, prd, prt, pre]
filename = []
filepath = []
crc32 = []
filecount = 0
currentfile = 0
count = 0

id_file = 'last_id.txt'
start_id = 7777777000

def clear():
    os.system('cls' if os.name == 'nt' else 'clear')

def get_last_id():
    """Liest die zuletzt gespeicherte ID aus der Datei."""
    if os.path.exists(id_file):
        with open(id_file, 'r') as f:
            return int(f.read().strip())
    return start_id

def save_last_id(last_id):
    """Speichert die letzte ID in die Datei."""
    with open(id_file, 'w') as f:
        f.write(str(last_id))

def getcrc32(f):
    with open(f, 'rb') as fo:
        file_content = fo.read()
        return binascii.crc32(file_content) & 0xffffffff

def properties(fileext, propertyext, propetytype):
    global currentfile, filecount, count
    last_id = get_last_id()

    for srcfn in glob.glob('*%s' % fileext):
        if '_lod_0' in srcfn:  # skip LOD files
            pass
        else:
            filename.append(srcfn)
            filepath.append((os.getcwd() + '/%s' % srcfn).replace('\\', '/').lower())
            filecount += 1

    for i in range(0, len(filename)):
        with open(filename[i][:-4] + propertyext, 'w') as prop:
            prop.write('YPRT\n')
            crc32.append(getcrc32(filename[i]))
            prop.write(str(crc32[i]) + '\n')
            if propertyext == '.prb':
                prop.write('buildingfile\t\t"%s"' % filepath[i].lower())
                if os.path.exists(filename[i][:-4] + '.mdatr'):
                    prop.write('\nisattributedata\t\t"0"')  # include .mdatr
            if propertyext == '.prd':
                prop.write('dungeonblockfile\t\t"%s"' % filepath[i].lower())
            if propertyext == '.prt':
                prop.write('treefile\t\t"%s"' % filepath[i].lower())
            if propertyext == '.pre':
                prop.write('effectfile\t\t"%s"' % filepath[i].lower())
            prop.write('\npropertyname\t\t"%s"\n' % filename[i][:-4])
            prop.write('propertytype\t\t"%s"\n' % propetytype)
            if propertyext == '.prb' and bshadow == 'T':
                prop.write('shadowflag\t\t"1"\n')  # include shadow
            if propertyext == '.prt':
                prop.write('treesize\t\t"1000.000000"\n')
                prop.write('treevariance\t\t"0.000000"')

            prop.write('propertyid\t\t"%d"\n' % last_id)
            print("(%d/%d) %s | crc32: %d | ID: %d" % (currentfile + 1, filecount, filename[i], crc32[i], last_id))

            last_id += 1

            currentfile += 1
            count += 1

    save_last_id(last_id)

def option(ext):
    global bshadow

    if ext == prb:
        outputshadow = input("Include shadows? (T/N): ")
        if outputshadow.lower() == 't':
            bshadow += 'T'
        properties('.gr2', '.prb', 'Building')
    if ext == prd:
        properties('.gr2', '.prd', 'DungeonBlock')
    if ext == prt:
        properties('.spt', '.prt', 'Tree')
    if ext == pre:
        properties('.mse', '.pre', 'Effect')

def menu():
    print("1) ", prb)
    print("2) ", prd)
    print("3) ", prt)
    print("4) ", pre)
    select = input("Choose option: ")
    if 5 > int(select) > 0:
        clear()
        print("You have chosen: ", filetype[int(select) - 1])
        option(filetype[int(select) - 1])
    else:
        clear()
        menu()

menu()
print("Generated", count)
input("Press any key to exit")

 

 

 

Link to comment
https://metin2.dev/topic/11267-batch-property-generator/#findComment-167001
Share on other sites

Don't use any images from : imgur, turkmmop, freakgamers, inforge, hizliresim... Or your content will be deleted without notice...
Use : https://metin2.download/media/add/

Please use https://metin2.download/ when uploading files smaller than 100MB, otherwise the approval will take longer due to manual upload.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • 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.