mirror of
https://github.com/HerculesWS/Hercules
synced 2026-08-15 12:23:13 -04:00
264 lines
8.4 KiB
Python
Executable file
264 lines
8.4 KiB
Python
Executable file
#!/usr/bin/python
|
|
# -*- coding: utf8 -*-
|
|
#
|
|
# This file is part of Hercules.
|
|
# http://herc.ws - http://github.com/HerculesWS/Hercules
|
|
#
|
|
# Copyright (C) 2018-2026 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])
|