#! /usr/bin/env python3
# -*- coding: utf8 -*-
#
# This file is part of Hercules.
# http://herc.ws - http://github.com/HerculesWS/Hercules
#
# Copyright (C) 2015-2020 Hercules Dev Team
# Copyright (C) 2015 Andrei Karas (4144)
#
# Hercules is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This Script converts mob_db.txt to mob_db.conf format
import os
import re
import sys
comaSplit = re.compile(",")
def printHeader():
print("""mob_db: (
// Mobs Database
//
/******************************************************************************
************* Entry structure ************************************************
******************************************************************************
{
// =================== Mandatory fields ===============================
Id: ID (int)
SpriteName: "SPRITE_NAME" (string)
Name: "Mob name" (string)
// =================== Optional fields ================================
Lv: level (int, defaults to 1)
Hp: health (int, defaults to 1)
Sp: mana (int, defaults to 0)
Exp: basic experience (int, defaults to 0)
JExp: job experience (int, defaults to 0)
AttackRange: attack range (int, defaults to 1)
Attack: [attack1, attack2] (int, defaults to 0)
Def: defence (int, defaults to 0)
Mdef: magic defence (int, defaults to 0)
Stats: {
Str: strength (int, defaults to 0)
Agi: agility (int, defaults to 0)
Vit: vitality (int, defaults to 0)
Int: intelligence (int, defaults to 0)
Dex: dexterity (int, defaults to 0)
Luk: luck (int, defaults to 0)
}
ViewRange: view range (int, defaults to 1)
ChaseRange: chase range (int, defaults to 1)
Size: size (int, defaults to 1)
Race: race (int, defaults to 0)
Element: (type, level)
Mode: {
CanMove: true/false (bool)
Looter: true/false (bool)
Aggressive: true/false (bool)
Assist: true/false (bool)
CastSensorIdle:true/false (bool)
Boss: true/false (bool)
Plant: true/false (bool)
CanAttack: true/false (bool)
Detector: true/false (bool)
CastSensorChase: true/false (bool)
ChangeChase: true/false (bool)
Angry: true/false (bool)
ChangeTargetMelee: true/false (bool)
ChangeTargetChase: true/false (bool)
TargetWeak: true/false (bool)
}
MoveSpeed: move speed (int, defaults to 0)
AttackDelay: attack delay (int, defaults to 4000)
AttackMotion: attack motion (int, defaults to 2000)
DamageMotion: damage motion (int, defaults to 0)
MvpExp: mvp experience (int, defaults to 0)
MvpDrops: {
AegisName: chance (string: int)
...
}
Drops: {
AegisName: chance (string: int)
...
}
},
******************************************************************************/
""")
def printFooter():
print(")")
def printField(name, value):
print("\t{0}: {1}".format(name, value))
def printField2(name, value):
print("\t\t{0}: {1}".format(name, value))
def printFieldCond2(cond, name):
if cond != 0:
print("\t\t{0}: true".format(name))
def printFieldArr(name, value, value2):
print("\t{0}: [{1}, {2}]".format(name, value, value2))
def printFieldStr(name, value):
print("\t{0}: \"{1}\"".format(name, value))
def startGroup(name):
print("\t{0}: {{".format(name))
def endGroup():
print("\t}")
def printHelp():
print("MobDB converter from txt to conf format")
print("Usage:")
print(" mobdbconverter.py re serverpath dbfilepath")
print(" mobdbconverter.py pre-re serverpath dbfilepath")
print("Usage for read from stdin:")
print(" mobdbconverter.py re dbfilepath")
def isHaveData(fields, start, cnt):
for f in range(0, cnt):
value = fields[start + f * 2]
chance = fields[start + f * 2]
if value == "" or value == "0" or chance == "" or chance == "0":
continue
return True
return False
def convertToSize(size):
sizes = ["Size_Small", "Size_Medium", "Size_Large"]
if (size >= len(sizes)):
return size
return f'"{sizes[size]}"'
def convertToRace(race):
races = ["RC_Formless", "RC_Undead", "RC_Brute", "RC_Plant", "RC_Insect", "RC_Fish", "RC_Demon", "RC_DemiHuman", "RC_Angel", "RC_Dragon"]
if (race >= len(races)):
return race
return f'"{races[race]}"'
def convertToElement(element):
elements = ["Ele_Neutral", "Ele_Water", "Ele_Earth", "Ele_Fire", "Ele_Wind", "Ele_Poison", "Ele_Holy", "Ele_Dark", "Ele_Ghost", "Ele_Undead"]
if (element >= len(elements)):
return element
return f'"{elements[element]}"'
def convertFile(inFile, itemDb):
if inFile != "" and not os.path.exists(inFile):
return
if inFile == "":
r = sys.stdin
else:
r = open(inFile, "r")
printHeader()
for line in r:
if line.strip() == "":
continue
if len(line) < 5 or line[:2] == "//":
print(line)
continue
fields = comaSplit.split(line)
if len(fields) != 57:
print(line)
continue
for f in range(0, len(fields)):
fields[f] = fields[f].strip()
print("{")
printField("Id", fields[0])
printFieldStr("SpriteName", fields[1])
printFieldStr("Name", fields[2])
printField("Lv", fields[4])
printField("Hp", fields[5])
printField("Sp", fields[6])
printField("Exp", fields[7])
printField("JExp", fields[8])
printField("AttackRange", fields[9])
printFieldArr("Attack", fields[10], fields[11])
printField("Def", fields[12])
printField("Mdef", fields[13])
startGroup("Stats")
printField2("Str", fields[14])
printField2("Agi", fields[15])
printField2("Vit", fields[16])
printField2("Int", fields[17])
printField2("Dex", fields[18])
printField2("Luk", fields[19])
endGroup()
printField("ViewRange", fields[20])
printField("ChaseRange", fields[21])
printField("Size", convertToSize(int(fields[22])))
printField("Race", convertToRace(int(fields[23])))
print("\tElement: ({0}, {1})".format(convertToElement(int(fields[24]) % 10), int(int(fields[24]) / 20)));
mode = int(fields[25], 0)
if mode != 0:
startGroup("Mode")
printFieldCond2(mode & 0x0001, "CanMove")
printFieldCond2(mode & 0x0002, "Looter")
printFieldCond2(mode & 0x0004, "Aggressive")
printFieldCond2(mode & 0x0008, "Assist")
printFieldCond2(mode & 0x0010, "CastSensorIdle")
printFieldCond2(mode & 0x0020, "Boss")
printFieldCond2(mode & 0x0040, "Plant")
printFieldCond2(mode & 0x0080, "CanAttack")
printFieldCond2(mode & 0x0100, "Detector")
printFieldCond2(mode & 0x0200, "CastSensorChase")
printFieldCond2(mode & 0x0400, "ChangeChase")
printFieldCond2(mode & 0x0800, "Angry")
printFieldCond2(mode & 0x1000, "ChangeTargetMelee")
printFieldCond2(mode & 0x2000, "ChangeTargetChase")
printFieldCond2(mode & 0x4000, "TargetWeak")
printFieldCond2(mode & 0x8000, "LiveWithoutMaster")
endGroup()
printField("MoveSpeed", fields[26])
printField("AttackDelay", fields[27])
printField("AttackMotion", fields[28])
printField("DamageMotion", fields[29])
printField("MvpExp", fields[30])
if isHaveData(fields, 31, 3):
startGroup("MvpDrops")
for f in range(0, 3):
value = fields[31 + f * 2]
chance = fields[32 + f * 2]
if value == "" or value == "0" or chance == "" or chance == "0":
continue
value = int(value)
if value not in itemDb:
print("// Error: mvp drop with id {0} not found in item_db.conf".format(value))
else:
printField2(itemDb[value], chance)
endGroup()
if isHaveData(fields, 37, 10):
startGroup("Drops")
for f in range(0, 10):
value = fields[37 + f * 2]
chance = fields[38 + f * 2]
if value == "" or value == "0" or chance == "" or chance == "0":
continue
value = int(value)
if value not in itemDb:
print("// Error: drop with id {0} not found in item_db.conf".format(value))
else:
printField2(itemDb[value], chance)
endGroup()
print("},")
printFooter()
if inFile != "":
r.close()
def readItemDB(inFile, itemDb):
itemId = 0
itemName = ""
started = False
with open(inFile, "r") as r:
for line in r:
line = line.strip()
if started == True:
if line == "},":
started = False
elif line[:10] == "AegisName:":
itemName = line[12:-1]
elif line[:3] == "Id:":
try:
itemId = int(line[4:])
except ValueError:
started = False
if itemId != 0 and itemName != "":
# was need for remove wrong characters
# itemName = itemName.replace(".", "")
# if itemName[0] >= "0" and itemName[0] <= "9":
# itemName = "Num" + itemName
itemDb[itemId] = itemName
started = False
else:
if line == "{":
started = True
itemId = 0
itemName = ""
return itemDb
if len(sys.argv) != 4 and len(sys.argv) != 3:
printHelp()
exit(1)
startPath = sys.argv[2]
if len(sys.argv) == 4:
sourceFile = sys.argv[3]
else:
sourceFile = ""
itemDb = dict()
if sys.argv[1] == "re":
itemDb = readItemDB(startPath + "/db/re/item_db.conf", itemDb)
itemDb = readItemDB(startPath + "/db/item_db2.conf", itemDb)
elif sys.argv[1] == "pre-re":
itemDb = readItemDB(startPath + "/db/pre-re/item_db.conf", itemDb)
itemDb = readItemDB(startPath + "/db/item_db2.conf", itemDb)
else:
printHelp()
exit(1)
convertFile(sourceFile, itemDb)