summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xevolved.py844
1 files changed, 557 insertions, 287 deletions
diff --git a/evolved.py b/evolved.py
index 2d421bc..2065f54 100755
--- a/evolved.py
+++ b/evolved.py
@@ -13,6 +13,7 @@ import sys, traceback, re
aegis=open("../world/map/db/const-aegis.txt", "w")
description_m="//ID, Name, Jname, LV, HP, SP, EXP, JEXP, Range1, ATK1, ATK2, DEF, MDEF, CRITDEF,STR, AGI, VIT, INT, DEX, LUK, Range2, Range3, Scale, Race, Element,Mode, Speed, Adelay, Amotion,Dmotion,Drop0id,Drop0%, Drop1id,Drop1%, Drop2id,Drop2%, Drop3id,Drop3%, Drop4id,Drop4%, Drop5id,Drop5%, Drop6id,Drop6%, Drop7id,Drop7%, Drop8id,Drop8%, Drop9id,Drop9%, Item1, Item2, MEXP, ExpPer, MVP1id, MVP1per,MVP2id, MVP2per,MVP3id, MVP3per,mutationcount,mutationstrength"
+description_i="//ID, Name, Type, Price, Sell, Weight, ATK, DEF, Range, Mbonus, Slot, Gender, Loc, wLV, eLV, View, {UseScript}, {EquipScript}"
# the TYPEs we use to determine where to pack things
IT_HEALING=[]
@@ -22,7 +23,7 @@ IT_AMMO=[]
IT_CARD=[]
IT_PETEGG=[]
IT_WEAPON={ 'HAND_2': [], # TWO HAND (LR)
- 'HAND_1':[]} # WEAPONS (R)
+ 'HAND_1': []} # WEAPONS (R)
IT_ARMOR={ 'MISC': [], # FOR FAILURE
'EQP_ACC_L': [], # ACCESSORY LEFT
'EQP_ACC_R': [], # ACCESSORT RIGHT
@@ -46,26 +47,538 @@ MobsA=[]
AllItems={}
-
+#############################################################################################
def printSeparator():
print("--------------------------------------------------------------------------------")
+#############################################################################################
def showHeader():
- print("Evolved->Legacy DB Generator")
+ print("Evol2->TMWA DB Generator")
print("Run at: " + datetime.datetime.now().isoformat())
#print("Usage: ./evolved.py [<path_to_serverdata> <path_to_clientdata>]")
printSeparator()
+#############################################################################################
def showFooter():
#pass
#printSeparator()
print("Done.")
+#############################################################################################
+def write_to_file(array, outfile, mode, description_count): # mode: 0 = item, 1 = mob
+
+ count=0
+ with open (outfile, "w") as f:
+ if mode:
+ write_mob_header(f)
+ else:
+ write_item_header(f)
+ for i in sorted(array, key=lambda xcv: int(xcv.id)):
+ if mode:
+ write_mob(i, f)
+ else:
+ write_item(i, f)
+
+ count+=1
+ if count >= description_count:
+ count=0
+ if mode:
+ f.write(description_m + "\n")
+ else:
+ f.write(description_i + "\n")
+
+ return
+
+
+# ___________
+# / \
+# / Items \
+# /_______________\
+# \_______________/
+
+"""
+struct Item
+{
+ Spanned<ItemNameId> id;
+ Spanned<ItemName> name;
+ Spanned<ItemType> type;
+ Spanned<int> buy_price;
+ Spanned<int> sell_price;
+ Spanned<int> weight;
+ Spanned<int> atk;
+ Spanned<int> def;
+ Spanned<int> range;
+ Spanned<int> magic_bonus;
+ Spanned<RString> slot_unused;
+ Spanned<SEX> gender;
+ Spanned<EPOS> loc;
+ Spanned<int> wlv;
+ Spanned<int> elv;
+ Spanned<ItemLook> view;
+ ast::script::ScriptBody use_script;
+ ast::script::ScriptBody equip_script;
+};
+enum class SEX : uint8_t
+{
+ FEMALE = 0,
+ MALE = 1,
+ // For items. This is also used as error, sometime.
+ // TODO switch to Option<SEX> where appropriate.
+ UNSPECIFIED = 2,
+ NEUTRAL = 3,
+ __OTHER = 4, // used in ManaPlus only
+};
+"""
+class It:
+ def __init__(self):
+ # Basic
+ self.id="0"
+ self.aegis="UnknownItem"
+ self.name="Unknown Item Name"
+ self.type="IT_ETC" # default type
+ self.buy="0"
+ self.sell="0"
+ self.weight="0"
+ self.atk="0"
+ self.matk="0"
+ self.df="0"
+ self.range="0"
+ self.sl="0" # Slots (unused always 0)
+ self.gender="2" # default = UNSPECIFIED = 2
+ self.loc=""
+ self.wlv="0" # 1 for weapons, 0 for all others including ammo
+ self.elv="0" # equip lvl
+ self.md=0 # mode not yet implemented in tmwa
+ self.subtype=""
+ self.disabled=False
+ # Script settings
+ self.usescript=[]
+ self.eqscript=[]
+ #self.usescript=""
+ #self.eqscript=""
+
+ # Special settings
+ self.rare=False # DropAnnounce
+
+ # Visual
+ self.ac=False # Allow Cards
+
+ self.gmlvlonly=False
+
+#############################################################################################
+def ItAlloc(it):
+ if (it.aegis == "UnknownItem"):
+ return
+ if (it.sl == "0" and it.ac) or (it.sl in ["1","2","3","4"] and not it.ac):
+ print("WARNING, item id "+it.id+" invalid dye/card setting!")
+ if (len(it.sl) > 1):
+ print("WARNING, item id "+it.id+" bad slots length: %d (%s)" % (len(it.sl), it.sl))
+
+ a=it.type
+ if "IT_HEALING" in a:
+ IT_HEALING.append(it)
+ elif "IT_ETC" in a:
+ IT_ETC.append(it)
+ elif "IT_USABLE" in a:
+ IT_USABLE.append(it)
+ elif "IT_AMMO" in a:
+ IT_AMMO.append(it)
+ elif "IT_CARD" in a:
+ IT_CARD.append(it)
+ elif "IT_PETEGG" in a:
+ IT_PETEGG.append(it)
+ elif "IT_WEAPON" in a:
+ if "HAND_L" in it.loc or "EQP_ARMS" in it.loc:
+ IT_WEAPON["HAND_2"].append(it)
+ elif "HAND_R" in it.loc:
+ IT_WEAPON["HAND_1"].append(it)
+ else:
+ raise Exception("Invalid location for weapon: %s" % it.loc)
+ elif "IT_ARMOR" in a:
+ if 'EQP_ACC_L' in it.loc:
+ IT_ARMOR['EQP_ACC_L'].append(it)
+ elif 'EQP_ACC_R' in it.loc:
+ IT_ARMOR['EQP_ACC_R'].append(it)
+ elif 'EQP_HEAD_MID' in it.loc:
+ IT_ARMOR['EQP_HEAD_MID'].append(it)
+ elif 'EQP_SHOES' in it.loc:
+ IT_ARMOR['EQP_SHOES'].append(it)
+ elif 'EQP_GARMENT' in it.loc:
+ IT_ARMOR['EQP_GARMENT'].append(it)
+ elif 'EQP_HEAD_LOW' in it.loc:
+ IT_ARMOR['EQP_HEAD_LOW'].append(it)
+ elif 'EQP_HEAD_TOP' in it.loc:
+ IT_ARMOR['EQP_HEAD_TOP'].append(it)
+ elif 'EQP_HAND_L' in it.loc:
+ IT_ARMOR['EQP_HAND_L'].append(it)
+ elif '1024' in it.loc:
+ IT_ARMOR['1024'].append(it)
+ elif '2048' in it.loc:
+ IT_ARMOR['2048'].append(it)
+ elif 'EQP_SHADOW_SHOES' in it.loc:
+ IT_ARMOR['EQP_MOUNT'].append(it)
+ elif 'EQP_ARMOR' in it.loc:
+ IT_ARMOR['EQP_ACC_R'].append(it) # Not really
+ else:
+ raise Exception("Invalid Loc for ID %s: %s" % (it.id, it.loc))
+ if "i" in it.id:
+ print("Invalid item: %s" % it.id)
+ return
+
+ ## Save the Aegis ID
+ if (it.aegis not in []):
+ aegis.write("%s %s\n" % (it.aegis, it.id))
+ else:
+ print("%s: Aegis reused as quest var (please purge)" % it.aegis)
+ AllItems[it.aegis]=str(it.id)
+
+#############################################################################################
+def newItemDB():
+ IT_NODROP = 1
+ IT_NOTRADE = 2
+ IT_NOSELLTONPC = 4
+ IT_NOSTORAGE = 8
+ IT_DROPANNOUNCE = 16
+
+ print("\nGenerating Item Wiki...")
+ if len(sys.argv) >= 2:
+ src=open(sys.argv[1]+"/db/pre-re/item_db.conf", "r")
+ else:
+ src=open("../world/map/db/item_db.conf", "r")
+
+ usescripting=False
+ eqscripting=False
+ useableitem=False
+ nouse=False
+
+ x=It()
+ for a in src:
+ # Evol2-only scripts
+ if "@EVOL2" in a:
+ continue
+ if "@TMWA" in a:
+ a=a.replace("//", "").replace("@TMWA", "")
+ # Initiate the script
+ if a == "{\n":
+ ItAlloc(x)
+ x=It()
+ # sti() block
+ if "\tId:" in a:
+ x.id=sti(a)
+ elif "\tAegisName:" in a:
+ x.aegis=sti(a)
+ elif "\tName:" in a:
+ x.name=stin(a)
+ elif "\tBuy:" in a:
+ x.buy=sti(a)
+ elif "\tSell:" in a:
+ x.sell=sti(a)
+ elif "\tWeight:" in a:
+ x.weight=sti(a)
+ elif "\tType:" in a:
+ x.type=sti(a)
+ if x.type == "IT_USABLE":
+ useableitem=True
+ elif "\tLoc:" in a:
+ x.loc=sti(a)
+ elif "\tAtk:" in a:
+ x.atk=sti(a)
+ elif "\tMatk:" in a: # description says ignored in pre-re
+ x.matk=sti(a)
+ elif "\tRange:" in a:
+ x.range=sti(a)
+ elif "\tDef:" in a:
+ x.df=sti(a)
+ elif "\tEquipLv:" in a:
+ x.elv=sti(a)
+ #elif "\tSlots:" in a: # allways 0 in tmwa atm
+ #x.sl=sti(a)
+ elif "\tGender:" in a: # allways 2 in tmwa atm
+ x.gender=sti(a)
+ elif "\tSubtype:" in a:
+ x.subtype=sti(a)
+ elif "\tDisabled: true" in a:
+ x.disabled=True
+ elif "\tAllowCards:" in a:
+ x.ac=True
+ # Write booleans
+ elif "\tDropAnnounce: true" in a:
+ x.rare=True
+ #x.md = x.md | IT_DROPANNOUNCE
+ elif "\tnodrop: true" in a:
+ #x.drop=False
+ x.md = x.md | IT_NODROP
+ elif "\tnotrade: true" in a:
+ #x.trade=False
+ x.md = x.md | IT_NOTRADE
+ elif "\tnoselltonpc: true" in a:
+ #x.sell=False
+ x.md = x.md | IT_NOSELLTONPC
+ elif "\tnostorage: true" in a:
+ #x.store=False
+ x.md = x.md | IT_NOSTORAGE
+ elif "\tNouse:" in a:
+ nouse=True
+ elif "\toverride:" in a:
+ if nouse:
+ if sti(a) != "0":
+ x.gmlvlonly=True
+ elif "\t}" in a:
+ if nouse:
+ nouse=False
+ # FIXME: Different kind of scripts D:
+ elif "\tOnEquipScript:" in a:
+ eqscripting=True
+ elif "\tScript:" in a:
+ if useableitem:
+ usescripting=True
+ else:
+ eqscripting=True
+ # FIXME: Nesting D:
+ elif (eqscripting or usescripting) and '\t\">' in a:
+ eqscripting=False
+ usescripting=False
+ useableitem=False
+ elif eqscripting:
+ if re.search(r"^\t+//",a):
+ pass
+ #elif "bonus bMatkRate" in a: # its not that simple since it can be a bonus in tmwa as well so i must use the Matk: field
+ #x.matk=sti(a)
+ else:
+ x.eqscript.append(stis(a))
+ #print("%s" % a)
+ elif usescripting:
+ if re.search(r"^\t+//",a):
+ pass
+ else:
+ x.usescript.append(stis(a))
+
+ # Write last entry
+ ItAlloc(x)
+
+ src.close()
+
+#############################################################################################
+def sti(x):
+ return x.replace('\n', '').replace('|', '').replace(')', '').replace('Id: ', '').replace('"','').replace(';','').replace(" ","").replace("\t","").replace('AegisName: ', '').replace('Name: ','').replace('Buy: ', '').replace('Sell: ', '').replace('Weight: ', '').replace('Type: ', '').replace('Loc: ', '').replace('Atk: ', '').replace('Matk: ', '').replace('Range: ', '').replace('Def: ', '').replace('EquipLv: ', '').replace('Subtype: ', '').replace('Slots: ', '').replace('Gender: ', '').replace('nodrop: ', '').replace('notrade: ', '').replace('noselltonpc: ', '').replace('nostorage: ', '').replace('override: ', '').replace(" ", "").strip()
+
+#############################################################################################
+def stis(x):
+ x=re.sub(r'; *//.*$',';',x)
+ # handle those with @EVOL2 and @TMWA tags rather?
+ x=re.sub(r', EQI_.*;',';',x)
+ x=re.sub(r'readparam\(b(.*)\)',r'\1',x)
+ x=re.sub(r'callfunc "itheal", (-?[0-9]+), (-?[0-9]+).*',r'heal \1, \2, 1;',x)
+ x=re.sub(r'callfunc "RequireStat", b(.*), ([0-9]+).*',r'set @bStat, \1; set @minbStatVal, \2; callfunc "RequireStat";',x)
+ x=re.sub(r'callfunc\("SC_Bonus", (-?[0-9]+), SC_PLUSATTACKPOWER, (-?[0-9]+).*',r'sc_start sc_raiseattackstrength, \1, \2;',x)
+ x=re.sub(r'callfunc\("SC_Bonus", (-?[0-9]+), SC_ATTHASTE_POTION1, (-?[0-9]+).*',r'sc_start sc_raiseattackspeed0, \1, \2;',x)
+ x=re.sub(r'callfunc\("SC_Bonus", (-?[0-9]+), SC_SLOWPOISON, (-?[0-9]+).*',r'sc_start sc_slowpoison, \1, \2;',x) # uses 180k in tmwa files but gets multiplied by 1000 in source if low evolved value is taken
+ x=re.sub(r'callfunc\("SC_Bonus", (-?[0-9]+), SC_BLOODING, (-?[0-9]+).*',r'sc_start sc_poison, \1, \2;',x)
+ x=re.sub(r' +',' ',x)
+ return x.replace('\n', '').replace("\t","").strip()
+
+#############################################################################################
+def stin(x):
+ return x.replace('\n', '').replace('|', '').replace(')', '').replace('Id: ', '').replace('"','').replace(" ","").replace("\t","").replace('Name: ','').replace(';','')
+
+#############################################################################################
+"""
+# Type
+enum class ItemType : uint8_t
+{
+ USE = 0, // in eA, healing only
+ _1 = 1, // unused
+ _2 = 2, // in eA, other usable items
+ JUNK = 3, // "useless" items (e.g. quests)
+ WEAPON = 4, // all weapons
+ ARMOR = 5, // all other equipment
+ _6 = 6, // in eA, card
+ _7 = 7, // in eA, pet egg
+ _8 = 8, // in eA, pet equipment
+ _9 = 9, // unused
+ ARROW = 10, // ammo
+ _11 = 11, // in eA, delayed use (special script)
+};
+# used in tmwa
+IT_USABLE
+IT_ETC
+IT_WEAPON
+IT_ARMOR
+IT_AMMO
+
+# View
+enum class ItemLook : uint16_t
+{
+ NONE = 0,
+ BLADE = 1, // or some other common weapons
+ SETZER_AND_SCYTHE = 3,
+ STAFF = 10,
+ BOW = 11,
+ COUNT = 17,
+};
+
+# Loc
+enum class EPOS : uint16_t
+{
+ ZERO = 0x0000, # 0
+
+ LEGS = 0x0001, # 1 EQP_HEAD_LOW
+ WEAPON = 0x0002, # 2 EQP_HAND_R = 1 Hand, [EQP_HAND_L,EQP_HAND_R] = 2 Hand
+ GLOVES = 0x0004, # 4 EQP_GARMENT
+ CAPE = 0x0008, # 8 EQP_ACC_L (Isis and such)
+ MISC1 = 0x0010, # 16 EQP_ARMOR (Amuletts, Mana pearl and such)
+ SHIELD = 0x0020, # 32 EQP_HAND_L
+ SHOES = 0x0040, # 64 EQP_SHOES
+ MISC2 = 0x0080, # 128 EQP_ACC_R (Rings)
+ HAT = 0x0100, # 256 EQP_HEAD_TOP
+ TORSO = 0x0200, # 512 EQP_HEAD_MID
+
+ ARROW = 0x8000, # 32768 EQP_AMMO
+};
+
+# used in current item_db.conf
+ Loc: "EQP_ACC_L"
+ Loc: "EQP_ACC_R"
+ Loc: "EQP_AMMO"
+ Loc: "EQP_ARMOR"
+ Loc: "EQP_GARMENT"
+ Loc: "EQP_HAND_L"
+ Loc: ["EQP_HAND_L", "EQP_HAND_R"]
+ Loc: "EQP_HAND_R"
+ Loc: "EQP_HEAD_LOW"
+ Loc: "EQP_HEAD_MID"
+ Loc: "EQP_HEAD_TOP"
+ Loc: "EQP_SHOES"
+"""
+def write_item(i, f):
+
+ md=str(i.md)
+
+ ## Type
+ if i.type == "IT_USABLE":
+ type="0"
+ elif i.type == "IT_ETC":
+ type="3"
+ elif i.type == "IT_WEAPON":
+ type="4"
+ elif i.type == "IT_ARMOR":
+ type="5"
+ elif i.type == "IT_AMMO":
+ type="10"
+
+ ## View
+ if i.aegis == "Setzer" or i.aegis == "Scythe":
+ view="3"
+ elif i.aegis == "SandCutter" or i.aegis == "Jackal" or i.aegis == "WoodenStaff" or i.aegis == "SweetTooth":
+ # why do SandCutter and Jackal use a value thats used for staffs? this value is never used though even for real staffs.
+ view="10"
+ elif i.subtype == "W_BOW":
+ view="11"
+ elif i.type == "IT_WEAPON":
+ view="1"
+ else:
+ view="0"
+
+ ## Loc
+ if i.loc == "EQP_HEAD_LOW":
+ loc="1"
+ elif i.loc == "[EQP_HAND_L,EQP_HAND_R]" or i.loc == "EQP_HAND_R":
+ loc="2"
+ elif i.loc == "EQP_GARMENT":
+ loc="4"
+ elif i.loc == "EQP_ACC_L":
+ loc="8"
+ elif i.loc == "EQP_ARMOR":
+ loc="16"
+ elif i.loc == "EQP_HAND_L":
+ loc="32"
+ elif i.loc == "EQP_SHOES":
+ loc="64"
+ elif i.loc == "EQP_ACC_R":
+ loc="128"
+ elif i.loc == "EQP_HEAD_TOP":
+ loc="256"
+ elif i.loc == "EQP_HEAD_MID":
+ loc="512"
+ elif i.loc == "EQP_AMMO":
+ loc="32768"
+ else:
+ loc="0"
+
+ if i.disabled:
+ i.id="//"+i.id
+ if i.gmlvlonly:
+ i.eqscript.insert(0, "callfunc \"RestrictedItem\";")
+
+ ## Add spaces
+ i.id=i.id+','+' '*(len(re.findall('//ID, *', description_i)[0])-len(i.id)-1)
+ i.aegis=i.aegis+','+' '*(len(re.findall('Name, *', description_i)[0])-len(i.aegis)-1)
+ type=type+','+' '*(len(re.findall('Type, *', description_i)[0])-len(type)-1)
+ i.buy=i.buy+','+' '*(len(re.findall('Price, *', description_i)[0])-len(i.buy)-1)
+ i.sell=i.sell+','+' '*(len(re.findall('Sell, *', description_i)[0])-len(i.sell)-1)
+ i.weight=i.weight+','+' '*(len(re.findall('Weight, *', description_i)[0])-len(i.weight)-1)
+ i.atk=i.atk+','+' '*(len(re.findall('ATK, *', description_i)[0])-len(i.atk)-1)
+ i.df=i.df+','+' '*(len(re.findall('DEF, *', description_i)[0])-len(i.df)-1)
+ i.range=i.range+','+' '*(len(re.findall('Range, *', description_i)[0])-len(i.range)-1)
+ i.matk=i.matk+','+' '*(len(re.findall('Mbonus, *', description_i)[0])-len(i.matk)-1)
+ i.sl=i.sl+','+' '*(len(re.findall('Slot, *', description_i)[0])-len(i.sl)-1)
+ i.gender=i.gender+','+' '*(len(re.findall('Gender, *', description_i)[0])-len(i.gender)-1)
+ loc=loc+','+' '*(len(re.findall('Loc, *', description_i)[0])-len(loc)-1)
+ i.wlv=i.wlv+','+' '*(len(re.findall('wLV, *', description_i)[0])-len(i.wlv)-1)
+ i.elv=i.elv+','+' '*(len(re.findall('eLV, *', description_i)[0])-len(i.elv)-1)
+ view=view+','+' '*(len(re.findall('View, *', description_i)[0])-len(view)-1)
+ # i.md here then
+ usescriptstr='{'+' '.join(str(x) for x in i.usescript)+'}'
+ usescriptstr=usescriptstr+','+' '*(len(re.findall('{UseScript}, *', description_i)[0])-len(usescriptstr)-1)
+ eqscriptstr='{'+' '.join(str(x) for x in i.eqscript)+'}'
+ #eqscriptstr=eqscriptstr+','+' '*(len(re.findall('{EquipScript}, *', description_i)[0])-len(eqscriptstr)-1)
+
+ ## Write the line
+ f.write("""%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n""" % (i.id, i.aegis, type, i.buy, i.sell, i.weight, i.atk, i.df, i.range, i.matk, i.sl, i.gender, loc, i.wlv, i.elv, view, usescriptstr, eqscriptstr))
+ return
+
+#############################################################################################
+def write_item_header(f):
+ f.write("//THIS FILE IS GENERATED AUTOMATICALLY\n//DO NOT EDIT IT DIRECTLY\n//Edit item_db.conf instead!\n")
+ f.write(description_i + "\n")
+ return
+
+#############################################################################################
+def save_items():
+ global IT_ETC, IT_USABLE, IT_AMMO, IT_WEAPON, IT_ARMOR
+
+ ## Items
+
+ DESCRIPTION_AFTER=20
+
+ WEAPON=IT_WEAPON['HAND_2']+IT_WEAPON['HAND_1']+IT_AMMO
+ write_to_file(WEAPON, "../world/map/db/item_db_weapon.txt", 0, DESCRIPTION_AFTER)
+ write_to_file(IT_ARMOR['EQP_HEAD_MID'], "../world/map/db/item_db_chest.txt", 0, DESCRIPTION_AFTER)
+ write_to_file(IT_ARMOR['EQP_SHOES'], "../world/map/db/item_db_foot.txt", 0, DESCRIPTION_AFTER)
+ write_to_file(IT_ARMOR['EQP_GARMENT'], "../world/map/db/item_db_hand.txt", 0, DESCRIPTION_AFTER)
+ write_to_file(IT_ARMOR['EQP_HEAD_TOP'], "../world/map/db/item_db_head.txt", 0, DESCRIPTION_AFTER)
+ write_to_file(IT_ARMOR['EQP_HEAD_LOW'], "../world/map/db/item_db_leg.txt", 0, DESCRIPTION_AFTER)
+ write_to_file(IT_ARMOR['EQP_HAND_L'], "../world/map/db/item_db_offhand.txt", 0, DESCRIPTION_AFTER)
+ TRINKLET=IT_ARMOR['EQP_ACC_L']+IT_ARMOR['EQP_ACC_R']
+ write_to_file(TRINKLET, "../world/map/db/item_db_trinket.txt", 0, DESCRIPTION_AFTER)
+ write_to_file(IT_USABLE, "../world/map/db/item_db_use.txt", 0, DESCRIPTION_AFTER)
+ write_to_file(IT_ETC, "../world/map/db/item_db_generic.txt", 0, DESCRIPTION_AFTER)
+
+ return
+
+
+
+# __________
+# / \
+# / Mobs \
+# /______________\
+# \______________/
+
class Mob:
def __init__(self):
# Basic
@@ -120,6 +633,7 @@ class Mob:
self.mtstr="0"
self.drops=[]
+#############################################################################################
def MobAlloc(ab):
if ab.name == "Unknown Monster Name":
return
@@ -147,8 +661,7 @@ def MobAlloc(ab):
else:
print("WARNING, Disregarding \"%s\" (ID: %s) as invalid mob" % (ab.name, ab.id))
-
-
+#############################################################################################
def testMobs():
MD_CANMOVE = 1
MD_LOOTER = 2
@@ -158,6 +671,7 @@ def testMobs():
MD_BOSS = 32
MD_PLANT = 64
MD_CANATTACK = 128
+
print("\nGenerating Mob Database...")
if len(sys.argv) >= 2:
src=open(sys.argv[1]+"/db/pre-re/mob_db.conf", "r")
@@ -182,45 +696,45 @@ def testMobs():
start=True
x=Mob()
- if " Id:" in a:
+ if "\tId:" in a:
x.id=stp(a)
- elif " SpriteName:" in a:
+ elif "\tSpriteName:" in a:
x.aegis=stp(a)
- elif " Name:" in a:
+ elif "\tName:" in a:
x.name=stp(a)
- elif " Hp:" in a:
+ elif "\tHp:" in a:
x.hp=stp(a)
- elif " Sp:" in a:
+ elif "\tSp:" in a:
x.sp=stp(a)
- elif " Lv:" in a:
+ elif "\tLv:" in a:
x.mobpt=stp(a)
- elif " Exp:" in a:
+ elif "\tExp:" in a:
x.xp=stp(a)
- elif " JExp:" in a:
+ elif "\tJExp:" in a:
x.jp=stp(a)
- elif " MvpExp: " in a:
+ elif "\tMvpExp: " in a:
x.mvp=stp(a)
- elif " Def:" in a:
+ elif "\tDef:" in a:
x.df=stp(a)
- elif " Mdef:" in a:
+ elif "\tMdef:" in a:
x.mdf=stp(a)
- elif " CriticalDef:" in a:
+ elif "\tCriticalDef:" in a:
x.cdf=stp(a)
- elif " Attack:" in a:
+ elif "\tAttack:" in a:
x.atk=stp(a)
- elif " AttackRange:" in a:
+ elif "\tAttackRange:" in a:
x.range=stp(a)
- elif " MoveSpeed:" in a:
+ elif "\tMoveSpeed:" in a:
x.move=stp(a)
- elif " ViewRange:" in a:
+ elif "\tViewRange:" in a:
x.view=stp(a)
- elif " ChaseRange:" in a:
+ elif "\tChaseRange:" in a:
x.chase=stp(a)
- elif " AttackDelay:" in a:
+ elif "\tAttackDelay:" in a:
x.adelay=stp(a)
- elif " AttackMotion:" in a:
+ elif "\tAttackMotion:" in a:
x.amotion=stp(a)
- elif " DamageMotion:" in a:
+ elif "\tDamageMotion:" in a:
x.dmotion=stp(a)
elif "\tStr: " in a:
x.str=stp(a)
@@ -270,233 +784,23 @@ def testMobs():
x.md = x.md | MD_PLANT
elif "\tCanAttack: true" in a:
x.md = x.md | MD_CANATTACK
- elif 'Drops: ' in a:
+ elif '\tDrops: ' in a:
dropper=True
- elif dropper and '}' in a:
+ elif dropper and '\t}' in a:
dropper=False
elif dropper:
x.drops.append(stp(a).split(": "))
-
# Write last entry
MobAlloc(x)
src.close()
+#############################################################################################
def stp(x):
return x.replace('\n', '').replace('|', '').replace('(int, defaults to ', '').replace(')', '').replace('basic experience', '').replace('"','').replace(" ","").replace("\t","").replace('(string', '').replace('SpriteName: ','').replace('Name: ','').replace('AttackDelay: ', '').replace('AttackMotion: ', '').replace('DamageMotion: ', '').replace('MoveSpeed: ', '').replace('AttackRange: ', '').replace('ViewRange: ','').replace('ChaseRange: ','').replace('Attack: ','').replace('Hp: ','').replace('Sp: ','').replace('Id: ','').replace('Lv: ','').replace('view range','').replace('attack range','').replace('move speed','').replace('health','').replace('(int','').replace('attack delay','atk.').replace("Str:", "").replace("Agi:", "").replace("Vit:", "").replace("Int:", "").replace("Dex:", "").replace("Luk:", "").replace("Mdef:","").replace("CriticalDef:","").replace("Def:","").replace("Size:","").replace("Race:", "").replace("Element:","").replace("JExp: ","").replace("MvpExp: ","").replace("Exp: ","").replace("MutationCount: ","").replace("MutationStrength: ","").strip()
-
-
-
-
-
-
-
-
-
-
-
-class It:
- def __init__(self):
- # Basic
- self.id="0"
- self.aegis="UnknownItem"
- self.name="Unknown Item Name"
- self.buy="0"
- self.sell="0"
- self.weight="0"
- self.type="IT_ETC" # default type
- self.loc=""
-
- # Offensive/Defensive
- self.atk="0"
- self.matk="0"
- self.range="0"
- self.defs="0"
- self.wlvl="0" # TODO
-
- # Restrictions (EquipLv)
- self.lvl="0"
- self.drop=True
- self.trade=True
- self.sell=True
- self.store=True
-
- # Special settings
- self.rare=False # DropAnnounce
- self.script=False
-
- # Visual
- self.sl="0" # Slots
- self.ac=False # Allow Cards
-
- # Script settings
- self.script=[]
-
-def ItAlloc(it):
- if (it.aegis == "UnknownItem"):
- return
- if (it.sl == "0" and it.ac) or (it.sl in ["1","2","3","4"] and not it.ac):
- print("WARNING, item id "+it.id+" invalid dye/card setting!")
- if (len(it.sl) > 1):
- print("WARNING, item id "+it.id+" bad slots length: %d (%s)" % (len(it.sl), it.sl))
-
- a=it.type
- if "IT_HEALING" in a:
- IT_HEALING.append(it)
- elif "IT_ETC" in a:
- IT_ETC.append(it)
- elif "IT_USABLE" in a:
- IT_USABLE.append(it)
- elif "IT_AMMO" in a:
- IT_AMMO.append(it)
- elif "IT_CARD" in a:
- IT_CARD.append(it)
- elif "IT_PETEGG" in a:
- IT_PETEGG.append(it)
-
- elif "IT_WEAPON" in a:
- if "HAND_L" in it.loc or "EQP_ARMS" in it.loc:
- IT_WEAPON["HAND_2"].append(it)
- elif "HAND_R" in it.loc:
- IT_WEAPON["HAND_1"].append(it)
- else:
- raise Exception("Invalid location for weapon: %s" % it.loc)
-
- elif "IT_ARMOR" in a:
- if 'EQP_ACC_L' in it.loc:
- IT_ARMOR['EQP_ACC_L'].append(it)
- elif 'EQP_ACC_R' in it.loc:
- IT_ARMOR['EQP_ACC_R'].append(it)
- elif 'EQP_HEAD_MID' in it.loc:
- IT_ARMOR['EQP_HEAD_MID'].append(it)
- elif 'EQP_SHOES' in it.loc:
- IT_ARMOR['EQP_SHOES'].append(it)
- elif 'EQP_GARMENT' in it.loc:
- IT_ARMOR['EQP_GARMENT'].append(it)
- elif 'EQP_HEAD_LOW' in it.loc:
- IT_ARMOR['EQP_HEAD_LOW'].append(it)
- elif 'EQP_HEAD_TOP' in it.loc:
- IT_ARMOR['EQP_HEAD_TOP'].append(it)
- elif 'EQP_HAND_L' in it.loc:
- IT_ARMOR['EQP_HAND_L'].append(it)
- elif '1024' in it.loc:
- IT_ARMOR['1024'].append(it)
- elif '2048' in it.loc:
- IT_ARMOR['2048'].append(it)
- elif 'EQP_SHADOW_SHOES' in it.loc:
- IT_ARMOR['EQP_MOUNT'].append(it)
- elif 'EQP_ARMOR' in it.loc:
- IT_ARMOR['EQP_ACC_R'].append(it) # Not really
- else:
- raise Exception("Invalid Loc for ID %s: %s" % (it.id, it.loc))
-
- if "i" in it.id:
- print("Invalid item: %s" % it.id)
- return
-
- ## Save the Aegis ID
- if (it.aegis not in []):
- aegis.write("%s %s\n" % (it.aegis, it.id))
- else:
- print("%s: Aegis reused as quest var (please purge)" % it.aegis)
- AllItems[it.aegis]=str(it.id)
-
-
-
-
-def newItemDB():
- print("\nGenerating Item Wiki...")
- if len(sys.argv) >= 2:
- src=open(sys.argv[1]+"/db/pre-re/item_db.conf", "r")
- else:
- src=open("../world/map/db/item_db.conf", "r")
-
- scripting=False
- x=It()
- for a in src:
- # Evol2-only scripts
- if "@EVOL2" in a:
- continue
- if "@TMWA" in a:
- a=a.replace("//", "").replace("@TMWA", "")
- # Initiate the script
- if a == "{\n":
- ItAlloc(x)
- x=It()
- # sti() block
- if " Id:" in a:
- x.id=sti(a)
- elif " AegisName:" in a:
- x.aegis=sti(a)
- elif " Name:" in a:
- x.name=stin(a)
- elif " Buy:" in a:
- x.buy=sti(a)
- elif " Sell:" in a:
- x.sell=sti(a)
- elif " Weight:" in a:
- x.weight=sti(a)
- elif " Type:" in a:
- x.type=sti(a)
- elif " Loc:" in a:
- x.loc=sti(a)
- elif " Atk:" in a:
- x.atk=sti(a)
- elif " Matk:" in a:
- x.matk=sti(a)
- elif " Range:" in a:
- x.range=sti(a)
- elif " Def:" in a:
- x.defs=sti(a)
- elif " EquipLv:" in a:
- x.lvl=sti(a)
- elif " Slots:" in a:
- x.sl=sti(a)
- elif " AllowCards:" in a:
- x.ac=True
- # Write booleans
- elif "DropAnnounce: true" in a:
- x.rare=True
- elif "nodrop: true" in a:
- x.drop=False
- elif "notrade: true" in a:
- x.trade=False
- elif "noselltonpc: true" in a:
- x.sell=False
- elif "nostorage: true" in a:
- x.store=False
- # FIXME: Different kind of scripts D:
- elif "Script" in a:
- scripting=True
- # FIXME: Nesting D:
- elif scripting and '}' in a:
- scripting=False
- elif scripting:
- x.script.append(sti(a))
-
- # Write last entry
- ItAlloc(x)
-
- src.close()
-
-def sti(x):
- return x.replace('\n', '').replace('|', '').replace(')', '').replace('Id: ', '').replace('"','').replace(" ","").replace("\t","").replace('AegisName: ', '').replace('Name: ','').replace('Buy: ', '').replace('Sell: ', '').replace('Weight: ', '').replace('Type: ', '').replace('Loc: ', '').replace('Atk: ', '').replace('Matk: ', '').replace('Range: ', '').replace('Def: ', '').replace('EquipLv: ', '').replace('Slots: ','').replace(" ", "").strip()
-
-def stin(x):
- return x.replace('\n', '').replace('|', '').replace(')', '').replace('Id: ', '').replace('"','').replace(" ","").replace("\t","").replace('Name: ','').replace(';','')
-
-
-
-
-
-
-
-
-
-
-
+#############################################################################################
def write_mob(m, f):
## Prepare new drop list
i=0
@@ -610,74 +914,40 @@ dl[6],dl[7], dl[8],dl[9], dl[10],dl[11], dl[12],dl[13], dl[14],dl[15],
dl[16],dl[17], dl[18],dl[19], item1, item2, m.mvp, expper, mvp1id, mvp1p, mvp2id, mvp2p, mvp3id, mvp3p, m.mtcnt, m.mtstr))
return
+#############################################################################################
def write_mob_header(f):
f.write("//THIS FILE IS GENERATED AUTOMATICALLY\n//DO NOT EDIT IT DIRECTLY\n//Edit mob_db.conf instead!\n")
f.write(description_m + "\n")
return
+#############################################################################################
def save_mobs():
global Mobs1, Mobs2, Mobs3, Mobs4, Mobs5, Mobs6, MobsA
- ## Mobs
- with open ("../world/map/db/mob_db_0_19.txt", "w") as f:
- write_mob_header(f)
- for m in sorted(Mobs1, key=lambda xcv: xcv.id):
- write_mob(m, f)
- continue
-
- with open ("../world/map/db/mob_db_20_39.txt", "w") as f:
- write_mob_header(f)
- for m in sorted(Mobs2, key=lambda xcv: xcv.id):
- write_mob(m, f)
- continue
-
- with open ("../world/map/db/mob_db_40_59.txt", "w") as f:
- write_mob_header(f)
- for m in sorted(Mobs3, key=lambda xcv: xcv.id):
- write_mob(m, f)
- continue
-
- with open ("../world/map/db/mob_db_60_79.txt", "w") as f:
- write_mob_header(f)
- for m in sorted(Mobs4, key=lambda xcv: xcv.id):
- write_mob(m, f)
- continue
-
- with open ("../world/map/db/mob_db_80_99.txt", "w") as f:
- write_mob_header(f)
- for m in sorted(Mobs5, key=lambda xcv: xcv.id):
- write_mob(m, f)
- continue
- with open ("../world/map/db/mob_db_over_100.txt", "w") as f:
- write_mob_header(f)
- for m in sorted(Mobs6, key=lambda xcv: xcv.id):
- write_mob(m, f)
- continue
+ DESCRIPTION_AFTER=20
- with open ("../world/map/db/mob_db_over_150.txt", "w") as f:
- write_mob_header(f)
- for m in sorted(MobsA, key=lambda xcv: xcv.id):
- write_mob(m, f)
- continue
+ ## Mobs
+
+ write_to_file(Mobs1, "../world/map/db/mob_db_0_19.txt", 1, DESCRIPTION_AFTER)
+ write_to_file(Mobs2, "../world/map/db/mob_db_20_39.txt", 1, DESCRIPTION_AFTER)
+ write_to_file(Mobs3, "../world/map/db/mob_db_40_59.txt", 1, DESCRIPTION_AFTER)
+ write_to_file(Mobs4, "../world/map/db/mob_db_60_79.txt", 1, DESCRIPTION_AFTER)
+ write_to_file(Mobs5, "../world/map/db/mob_db_80_99.txt", 1, DESCRIPTION_AFTER)
+ write_to_file(Mobs6, "../world/map/db/mob_db_over_100.txt", 1, DESCRIPTION_AFTER)
+ write_to_file(MobsA, "../world/map/db/mob_db_over_150.txt", 1, DESCRIPTION_AFTER)
return
-
-
-
-
-
-
-
-
+#############################################################################################
showHeader()
newItemDB()
testMobs()
+save_items()
save_mobs()
aegis.close()