#!/usr/bin/python
# -*- coding: utf8 -*-
#
# This file is part of Hercules.
# http://herc.ws - http://github.com/HerculesWS/Hercules
#
# Copyright (C) 2018-2020 Hercules Dev Team
# Copyright (C) 2018 Asheraf
#
# 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/>.
import re
import sys
import utils.common as Tools
SKILL_STATES = {
"any": "MSS_ANY",
"idle": "MSS_IDLE",
"walk": "MSS_WALK",
"loot": "MSS_LOOT",
"dead": "MSS_DEAD",
"attack": "MSS_BERSERK",
"angry": "MSS_ANGRY",
"chase": "MSS_RUSH",
"follow": "MSS_FOLLOW",
"anytarget": "MSS_ANYTARGET"
}
SKILL_COND1 = {
"always": "MSC_ALWAYS",
"myhpltmaxrate": "MSC_MYHPLTMAXRATE",
"myhpinrate": "MSC_MYHPINRATE",
"friendhpltmaxrate": "MSC_FRIENDHPLTMAXRATE",
"friendhpinrate": "MSC_FRIENDHPINRATE",
"mystatuson": "MSC_MYSTATUSON",
"mystatusoff": "MSC_MYSTATUSOFF",
"friendstatuson": "MSC_FRIENDSTATUSON",
"friendstatusoff": "MSC_FRIENDSTATUSOFF",
"attackpcgt": "MSC_ATTACKPCGT",
"attackpcge": "MSC_ATTACKPCGE",
"slavelt": "MSC_SLAVELT",
"slavele": "MSC_SLAVELE",
"closedattacked": "MSC_CLOSEDATTACKED",
"longrangeattacked": "MSC_LONGRANGEATTACKED",
"skillused": "MSC_SKILLUSED",
"afterskill": "MSC_AFTERSKILL",
"casttargeted": "MSC_CASTTARGETED",
"rudeattacked": "MSC_RUDEATTACKED",
"masterhpltmaxrate": "MSC_MASTERHPLTMAXRATE",
"masterattacked": "MSC_MASTERATTACKED",
"alchemist": "MSC_ALCHEMIST",
"onspawn": "MSC_SPAWN"
}
SKILL_COND2 = {
"anybad": "MSC_ANY",
"stone": "SC_STONE",
"freeze": "SC_FREEZE",
"stun": "SC_STUN",
"sleep": "SC_SLEEP",
"poison": "SC_POISON",
"curse": "SC_CURSE",
"silence": "SC_SILENCE",
"confusion": "SC_CONFUSION",
"blind": "SC_BLIND",
"hiding": "SC_HIDING",
"sight": "SC_SIGHT"
}
SKILL_TARGET = {
"target": "MST_TARGET",
"randomtarget": "MST_RANDOM",
"self": "MST_SELF",
"friend": "MST_FRIEND",
"master": "MST_MASTER",
"around5": "MST_AROUND5",
"around6": "MST_AROUND6",
"around7": "MST_AROUND7",
"around8": "MST_AROUND8",
"around1": "MST_AROUND1",
"around2": "MST_AROUND2",
"around3": "MST_AROUND3",
"around4": "MST_AROUND4",
"around": "MST_AROUND"
}
def printHeader():
print("""
mob_skill_db:(
{
/**************************************************************************
************* Entry structure ********************************************
**************************************************************************
<Monster_Constant>: {
<Skill_Constant>: {
ClearSkills: (boolean, defaults to false) allows cleaning all previous defined skills for the mob.
SkillLevel: (int, defaults to 1)
SkillState: (int, defaults to 0)
SkillTarget: (int, defaults to 0)
Rate: (int, defaults to 1)
CastTime: (int, defaults to 0)
Delay: (int, defaults to 0)
Cancelable: (boolean, defaults to false)
CastCondition: (int, defaults to 0)
ConditionData: (int, defaults to 0)
val0: (int, defaults to 0)
val1: (int, defaults to 0)
val2: (int, defaults to 0)
val3: (int, defaults to 0)
val4: (int, defaults to 0)
Emotion: (int, defaults to 0)
ChatMsgID: (int, defaults to 0)
}
}
**************************************************************************/""")
def printFooter():
print('}\n)\n')
def isValidEntry(line):
if re.match('^[0-9]+,.*', line):
return True
return False
def commaSplit(line):
return line.split(',')
def stripLinebreak(line):
return line.replace('\r', '').replace('\n', '')
def printInt(key, value):
if key in value:
if int(value[key]) is not 0:
print('\t\t\t{}: {}'.format(key, value[key]))
def printStrToInt(key, value):
if value[key] is not '':
if int(value[key]) is not 0:
print('\t\t\t{}: {}'.format(key, value[key]))
def printBool(key, value):
if value[key] == 'yes':
print('\t\t\t{}: true'.format(key))
def printClearSkills(key, value):
if value[key] == 'clear':
print('\t\t\t{}: true'.format(key))
def printSkillState(key, value):
if value[key]:
print('\t\t\t{}: "{}"'.format(key, SKILL_STATES[value[key]]))
def printSkillTarget(key, value):
if value[key]:
print('\t\t\t{}: "{}"'.format(key, SKILL_TARGET[value[key]]))
def printCastCondition(key, value):
if value[key]:
print('\t\t\t{}: "{}"'.format(key, SKILL_COND1[value[key]]))
def printConditionData(key, value):
if value[key] in SKILL_COND2:
print('\t\t\t{}: "{}"'.format(key, SKILL_COND2[value[key]]))
elif value[key] is not '':
if int(value[key]) is not 0:
print('\t\t\t{}: {}'.format(key, value[key]))
def printEmotion(key, value):
if value[key] is not '':
print('\t\t\t{}: {}'.format(key, value[key]))
def LoadOldDB(mode, serverpath):
r = open('{}db/{}/mob_skill_db.txt'.format(serverpath, mode), "r")
Db = dict()
for line in r:
if isValidEntry(line) == True:
entry = commaSplit(stripLinebreak(line))
MonsterId = entry[0]
if MonsterId not in Db:
Db[MonsterId] = dict()
skillidx = len(Db[MonsterId])
Db[MonsterId][skillidx] = dict()
Db[MonsterId][skillidx]['ClearSkills'] = entry[1]
Db[MonsterId][skillidx]['SkillState'] = entry[2]
Db[MonsterId][skillidx]['SkillId'] = entry[3]
Db[MonsterId][skillidx]['SkillLevel'] = entry[4]
Db[MonsterId][skillidx]['Rate'] = entry[5]
Db[MonsterId][skillidx]['CastTime'] = entry[6]
Db[MonsterId][skillidx]['Delay'] = entry[7]
Db[MonsterId][skillidx]['Cancelable'] = entry[8]
Db[MonsterId][skillidx]['SkillTarget'] = entry[9]
Db[MonsterId][skillidx]['CastCondition'] = entry[10]
Db[MonsterId][skillidx]['ConditionData'] = entry[11]
for i in range(5):
if entry[12 + i] is '':
continue
try:
Db[MonsterId][skillidx]['val{}'.format(i)] = int(entry[12 + i])
except ValueError:
Db[MonsterId][skillidx]['val{}'.format(i)] = int(entry[12 + i], 16)
Db[MonsterId][skillidx]['Emotion'] = entry[17]
Db[MonsterId][skillidx]['ChatMsgID'] = entry[18]
return Db
def ConvertDB(mode, serverpath):
db = LoadOldDB(mode, serverpath)
MobDB = Tools.LoadDBConsts('mob_db', mode, serverpath)
SkillDB = Tools.LoadDBConsts('skill_db', mode, serverpath)
printHeader()
for mobid in sorted(db.iterkeys()):
print('\t{}: {{'.format(MobDB[int(mobid)]))
for skillidx in sorted(db[mobid].iterkeys()):
valid = True
if int(db[mobid][skillidx]['SkillId']) not in SkillDB:
valid = False
print('/*')
print('// Can\'t find skill with id {} in skill_db'.format(db[mobid][skillidx]['SkillId']))
print('\t\t{}: {{'.format(db[mobid][skillidx]['SkillId']))
else:
print('\t\t{}: {{'.format(SkillDB[int(db[mobid][skillidx]['SkillId'])]))
printClearSkills('ClearSkills', db[mobid][skillidx])
printSkillState('SkillState', db[mobid][skillidx])
printStrToInt('SkillLevel', db[mobid][skillidx])
printStrToInt('Rate', db[mobid][skillidx])
printStrToInt('CastTime', db[mobid][skillidx])
printStrToInt('Delay', db[mobid][skillidx])
printBool('Cancelable', db[mobid][skillidx])
printSkillTarget('SkillTarget', db[mobid][skillidx])
printCastCondition('CastCondition', db[mobid][skillidx])
printConditionData('ConditionData', db[mobid][skillidx])
for i in range(5):
printInt('val{}'.format(i), db[mobid][skillidx])
printEmotion('Emotion', db[mobid][skillidx])
printStrToInt('ChatMsgID', db[mobid][skillidx])
print('\t\t}')
if valid is False:
print('*/')
print('\t}')
printFooter()
if len(sys.argv) != 3:
print('Monster Skill db converter from txt to conf format')
print('Usage:')
print(' mobskilldbconverter.py mode serverpath')
print("example:")
print(' mobskilldbconverter.py pre-re ../')
exit(1)
if sys.argv[1] != 're' and sys.argv[1] != 'pre-re':
print('you have entred an invalid server mode')
exit(1)
ConvertDB(sys.argv[1], sys.argv[2])