summaryrefslogblamecommitdiff
path: root/wiki/redesign.py
blob: 60bb4d7ba33fc537b5cb5a3784e09967c9c6ea38 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13












                                      
          
           
          
            







































































                                                                                                                                    
                                     
                               
                                                           
                                                                                        



                                    
                      
                        


                                    
                      
                        


                                   
                      



                                     
                      
                       


                                  
                     
                        

                   

                                                                                                      
                    
                                        















                     


                                








                   



























                                                     
                        




















































                                                                   
              









                                                                                       
                    






                                           

              


                     
                  























                          
                            













                        






























                                    

                                        
                          
                                                                         
         
                                                                              






                                                           

                                   






































                                   




                            















                                 

                                  











































                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  


                      
                 





                                                                                                                                                                      




                                                        





                                    
                                                             



























                                                                   
                                                                








































                                                                     
                                                                               














                                                            
                                                       
                                                      


                                                       










                                  


                




















































                                                                



                             
                           
 

                                     





                                        










                                                                



                                








                                         



                             











                                                                         
                              




































































                                                                                         



                             











                                                                                                                 










                                                                                       
                    
             
                    








                                                    
                              

                               
                                                                 
         


                    
 
                                     
         
               
                

                          



                                             

                   


              


                                                                 


                             


                
 







                                                                






                

                




                                                   
                                            




































                                                                                  
         







                                                             
                           









                                                                             

                                                                                              

























































































                                                                       






















                                 




                             


















                                                                                    

            
#! /usr/bin/env python3
# -*- coding: utf8 -*-
#
# Copyright (C) 2010-2011  Evol Online
# Copyright (C) 2018  TMW-2
# Author: Andrei Karas (4144)
# Author: Jesusalva
#
# The use of the data

import datetime
import sys

stgen=True
aeros=False
bifs=False
skipCI=False

wikib=open("EleMonsters.html", "w")
wikib.write('<html><head><meta charset=utf8 /><title>EleGen File</title></head><body>')

exp=[			9,16,25,36,77,112,153,200,253,320,
				385,490,585,700,830,970,1120,1260,1420,1620,
				1860,1990,2240,2504,2950,3426,3934,4474,6889,7995,
				9174,10425,11748,13967,15775,17678,19677,21773,28543,34212,
				38065,42102,46323,53026,58419,64041,69892,75973,92468,115254,
				128692,142784,157528,178184,196300,215198,234879,255341,310188,365914,
				402508,442769,487051,535756,589342,648281,713112,784421,862867,949158,
				1044076,1148484,1263331,1389671,1528642,1681509,1849671,2034639,2238111,
				2461928,
				2708132,2978946,3276840,3604530,3964987,4361495,4797656,5277432,5805184,6095442,
				6400217,6720231,7056251,7409070,7779531,8168509,8576941,9005793,9456080,9928893,
				10425342,10946613,11493946,12068655,12672087,13305690,13970980,14669530,15403013,16173172,
				16981833,17830934,18722479,19658611,20641552,21673632,22757319,23895184,25089950,25591758,
				26103599,26625670,27158181,27701356,28255388,28820507,29396920,29984867,30584571,31196260,
				31820184,32456596,33105727,33767845,34443202,35132065,35834705,36551410,37282446,38028099,
				38788671,39564454,40355745,41162860,41986116,42825838,43682362,44556009,45447138,45901616,
				46360641,46824255,47292503,47765432,48243093,48725528,49212784,49704921,50201982,50704003,
				51211047,51723162,52240405,52762810,53290446,53823354,54361598,54905214,55454271,56008820,
				56568910,57134610,57705965,58283032,58865873,59454536,60049086,60649586,61256083,61868649,
				62487336,63112216,63743344,64380779,65024597,65674843,66331602,66994930,67664885,68341538,
				69024959,69715207,70412360,71116485,71827658,72545940,73271398,74004114,74744153,75491595,
				76246518,77008984,77779077,78556879,79342456,80135878,80937236,81746616,82564087,83389730,
				84223638,85065880,85916545,86775711,87643468,88519912,89405121,90299171,91202163,92114182,
				93035322,93965687,94905347,95854406,96812948,97781076,98758892,99746478,100743951,101751398,
				102768911,103796609,104834582,105882930,106941769,108011193,109091315,110182230,111284052,112396904,
				113520874,114656091,115802657,116960692,118130296,119311601,120504716,121709770,122926875,124156150,
				125397711,126651686,127918206,129197392,130489375,131794267,133112212,134443338,135787774,137145652,
				138517109,139902284,141301316,142714335,144141489,145582902,147038738,148509126,149994219,150894194,
				151799571,152710366,153626627,154548387,155475676,156408540,157346998,158291079,159240837,160196288,
				161157464,162124419,163097165,164075757,165060214,166050576,167046878,168049166,169057470,170071823,
				171092262,172118826,173151541,174190460,175235604,176287026,177344758,178408837,179479294,180556179,
				181639518,182729367,183825754,184928711,186038293,187154528,188277464,189407130,190543577,191686849,
				192836981,193994007,195157974,196328927,197506910,198691949,199884102,201083405,202289908,203503646,
				204724676,205953024,207188754,208431886,209682484,210940582,212206225,213479467,214760350,216048919,
				217345224,218649298,219961193,221280960,222608645,223944302,225287974,226639708,227999552,229367554,
				230743762,232128226,233520999,234922133,236331675,237749668,239176170,240611236,242054915,243507252,
				244968307,246438117,247916753,249404252,250900687,252406101,253920540,255444067,256976742,258518609,
				260069729,261630158,263199938,264779135,266367816,267966025,269573820,271191260,272818408,274455326,
				276102061,277758679,279425234,281101787,282788399,284485141,286192050,287909214,289636677,291374496,
				293122752,294881486,296650782,298430689,300221275,302022609,303834742,305657759,307491713,309336672,
				311192696,313059863,314938223,316827859,318728836,320641216,322565061,324500459,326447460,328406143,
				330376584,332358847,334353004,336359128,338377288,340407551,342449994,344504696,346571722,348651151,
				350743062,352847532,354964629,357094423,359236990,361392422,363560778,365742141,367936599,370144221,
				372365091,374599279,376846874,379107955,381382611,383670915,385972949,388288794,390618537,392962257,
				395320037,397691969,400078129,402478601,404893475,407322841,409766782,412225383,414698739,417186939,
				419690069,422208209,424741456,427289911,429853651,432432776,435027370,437637543,440263366,442024421,
				443792521,445567690,447349963,449139360,450935926,452739673,454550638,456368839,458194326,460027115,
				461867221,463714693,465569558,467431848,469301579,471178794,473063508,474955766,476855601,478763022,
				480678083,482600803,484531205,486469328,488415217,490368880,492330355,494299675,496276878,498261990,
				500255043,502256068,504265102,506282171,508307305,510340540,512381907,514431439,516489176,518555144,
				520629376,522711891,524802748,526901963,529009581,531125618,533250127,535383137,537524678,539674777,
				541833486,544000830,546176836,548361554,550555012,552757234,554968274,557188159,559416915,561654583,
				563901210,566156820,568421455,570695142,572977924,575269847,577570928,579881219,582200741,584529542,
				586867672,589215145,591572009,593938303,596314063,598699319,601094122,603498497,605912494,608336152,
				610769496,613212575,615665434,618128102,620600617,623083026,625575357,628077658,630589971,633112332,
				635644789,638187373,640740134,643303101,645876314,648459827,651053675,653657891,656272528,658897623,
				661533224,664179368,666836088,669503437,672181451,674870184,677569669,680279959,683001081,685733085,
				688476023,691229930,693994859,696770843,699557927,702356165,705165600,707986270,710818214,713661496,
				716516145,719382218,722259755,725148792,728049398,730961596,733885443,736820993,739768279,742727359,
				745698276,748681079,751675801,754682510,757701238,760732051,763774987,766830096,769897426,772977027,
				776068941,779173220,782289911,785419075,788560754,791714999,794881861,798061393,801253640,804458666,
				807676501,810907214,814150847,817407448,820677081,823959788,827255638,830564665,833886935,837222492
				]

def printSeparator():
    print("--------------------------------------------------------------------------------")

def showHeader():
    global stgen, aeros, bifs, skipCI
    print("TMW2 Ele Generator")
    print("Run at: " + datetime.datetime.now().isoformat())
    print("Usage: ./redesign.py [default|aeros|none|update|all] [<path_to_serverdata>]")
    if len(sys.argv) >= 2:
        if sys.argv[1] == "default":
            stgen=True
            aeros=False
            bifs=False
            skipCI=False
        elif sys.argv[1] == "aeros":
            stgen=False
            aeros=True
            bifs=False
            skipCI=False
        elif sys.argv[1] == "none":
            stgen=False
            aeros=False
            bifs=False
            skipCI=False
        elif sys.argv[1] == "update":
            stgen=True
            aeros=False
            bifs=False
            skipCI=True
        elif sys.argv[1] == "all":
            stgen=True
            aeros=True
            bifs=True
            skipCI=False
        else:
            exit(1)
    print("This stuff analyzes and sorts monsters and then create base stats for Moubootaur Legends.")
    print("Drops aren't calculated or taken in account, TWEAK AS NEEDED")
    printSeparator()
    print("Output is: EleMonsters.html")

def showFooter():
    #pass
    #printSeparator()
    print("Done.")



Mobs1=[]
Mobs2=[]
Mobs3=[]
Mobs4=[]
Mobs5=[]
Mobs6=[]
MobsA=[]

# [N, W, E, F, W, -, H, H, G, -]
Ele=[0, 0, 0, 0, 0, 0, 0, 0, 0]

# This is for Aeros
Plants=[]
Level50=[]
Level100=[]
Aggressive=[]
Assistant=[]
Looter=[]
Boss=[]

SysDrops=[]

def fwalk(wmask):
    if wmask == 'WATER':
        return '<font color=#00f>%s</font>' % (wmask)
    elif wmask == 'AIR':
        return '<font color=#093>%s</font>' % (wmask)
    elif wmask == 'WALL':
        return '<font color=#f00>%s</font>' % (wmask)
    elif wmask == 'NORMAL' or wmask == 'DEFAULT':
        return '<font color=#111>%s</font>' % (wmask)
    else:
        print("Invalid walk mask: "+wmask)
        exit(1)

def WhatRace(rac):
    rc=rac.race
    if rc == 0:
        return "Formless"
    elif rc == 1:
        return "Undead"
    elif rc == 2:
        return "Brute"
    elif rc == 3:
        return "Plant"
    elif rc == 4:
        return "Insect"
    elif rc == 5:
        return "Mineral"
    elif rc == 6:
        return "-"
    elif rc == 7:
        return "SemiHuman"
    elif rc == 8:
        return "Angel"
    elif rc == 9:
        return "Dragon"
    elif rc == 10:
        return "Player"
    elif rc == 11:
        return "Boss"
    elif rc == 12:
        return "NonBoss"
    elif rc == 14:
        return "NonSemiHuman"
    elif rc == 15:
        return "NonPlayer"
    elif rc == 16:
        return "SemiPlayer"
    elif rc == 17:
        return "NonSemiPlayer"
    else:
        print("ERROR, INVALID RACE ID: %d (ID: %s)" % (rc, rac.id))
        exit(1)

def WhatElem(rac):
    rc=rac.elem
    tl="ERROR"
    cl="#F00"
    if rc == 0:
        tl,cl="Neutral","#000"
    elif rc == 1:
        tl,cl="Water","#00F"
    elif rc == 2:
        tl,cl="Earth","#7A0"
    elif rc == 3:
        tl,cl="Fire","#F00"
    elif rc == 4:
        tl,cl="Wind","#093"
    elif rc == 5:
        tl,cl="Nature","#040"
    elif rc == 6:
        tl,cl="Holy","#afa"
    elif rc == 7:
        tl,cl="Dark","#908"
    elif rc == 8:
        tl,cl="Ghost","#404"
    elif rc == 9:
        tl,cl="Undead","#440"
    else:
        print("ERROR, INVALID ELEM ID: %d (ID: %s)" % (rc, rac.id))
        exit(1)
    Ele[rc]+=1
    return "<font color=%s>%s</font>" % (cl, tl)

class Mob:
  def __init__(self):
    # Basic
    self.id="0"
    #self.aegis="UnknownMonster" # SpriteName is not used anywhere, we are using its ID
    self.name="Unknown Monster Name"
    self.view="1"
    self.boss=False
    self.plant=False

    # Defensive
    self.mobpt="0" # Mob Points “Level”
    self.hp="0"
    self.xp="Exp: 0"
    self.jp="JExp: 0"
    self.st=""
    self.dfn=0
    self.mdf=0

    # Offensive
    self.atk="[0, 0]"
    self.range="1"
    self.move="0"
    self.delay="0"
    self.drops=[]

    # New
    self.race=-1
    self.elem=-1
    self.elel=-1
    self.walk="NORMAL"

    # Stats
    self.str='0'
    self.agi='0'
    self.vit='0'
    self.int='0'
    self.dex='0'
    self.luk='0'

def MobAlloc(ab):
    try:
        maab=int(ab.mobpt)
    except:
        maab=9901

    if maab <= 20 or skipCI:
        Mobs1.append(ab)
    elif maab <= 40:
        Mobs2.append(ab)
    elif maab <= 60:
        Mobs3.append(ab)
    elif maab <= 80:
        Mobs4.append(ab)
    elif maab <= 100:
        Mobs5.append(ab)
    elif maab <= 150:
        Mobs6.append(ab)
    else:
        MobsA.append(ab)

    # Aeros allocation
    """Plants=[]
    Level50=[]
    Level100=[]
    Aggressive=[]
    Assistant=[]
    Looter=[]
    Boss=[]"""
    normie=True
    if ab.plant:
        Plants.append(ab.id)
        normie=False
    if ab.boss:
        Boss.append(ab.id)
        normie=False
    if normie:
        if "Agr" in ab.st:
            Aggressive.append(ab.id)
            normie=False
        if "Lot" in ab.st:
            Looter.append(ab.id)
            normie=False
        if "Ass" in ab.st:
            Assistant.append(ab.id)
            normie=False
    if normie:
        if maab <= 55:
            Level50.append(ab.id)
        else:
            Level100.append(ab.id)

def testMobs():
    print("Generating Elem-Mob Wiki...")
    if len(sys.argv) >= 3:
        src=open(sys.argv[2]+"/db/re/mob_db.conf", "r", encoding="utf-8")
    else:
        src=open("../../server-data/db/re/mob_db.conf", "r", encoding="utf-8")

    wikib.write("<h1 id=#x>EleGen Monster Database</h1>\n")
    start=False
    dropper=False
    skip=0
    x=Mob() # Only for pyflakes2

    for a2 in src:
        a=a2.replace('    ', '\t');
        if a == "{\n":
            if skip:
                skip=0
            if start:
                MobAlloc(x)
            else:
                start=True
            x=Mob()

        if skip:
            start=False
            x=Mob()
            continue
        if "	Id:" in a:
            x.id=stp(a)
        if x.id == "ID":
            continue

        if "	Name:" in a:
            x.name=stp(a)
        elif "	Hp:" in a:
            x.hp=stp(a)
        elif "	Lv:" in a:
            x.mobpt=stp(a)
        elif "	Exp:" in a:
            x.xp=stp(a)
        elif "	JExp:" in a:
            x.jp=stp(a)
        elif "	Attack:" in a:
            x.atk=stp(a)
        elif "	AttackRange:" in a:
            x.range=stp(a)
        elif "	MoveSpeed:" in a:
            x.move=stp(a)
        elif "	ViewRange:" in a:
            x.view=stp(a)
        elif "	AttackDelay:" in a:
            x.delay=stp(a)

        elif "	Def:" in a:
            x.dfn=stp(a)
        elif "	Mdef:" in a:
            x.mdf=stp(a)

        elif "	Str:" in a:
            x.str=stp(a)
        elif "	Agi:" in a:
            x.agi=stp(a)
        elif "	Vit:" in a:
            x.vit=stp(a)
        elif "	Int:" in a:
            x.int=stp(a)
        elif "	Dex:" in a:
            x.dex=stp(a)
        elif "	Luk:" in a:
            x.luk=stp(a)


        elif "	Boss: true" in a:
            x.boss=True
        elif "	Plant: true" in a:
            x.plant=True
        elif "	Looter: true" in a:
            x.st+="<font color=#790>Lot</font>,"
        elif "	Assist: true" in a:
            x.st+="<font color=#0a0>Ass</font>,"
        elif "	Aggressive: true" in a:
            x.st+="<font color=#f00>Agr</font>,"
        elif "	WalkMask:" in a:
            x.walk=stp(a)
        elif "	Element:" in a:
            tmp=stp(a)
            tmp2=tmp.split(',')
            try:
                x.elem=int(tmp2[0])
                x.elel=int(tmp2[1])
            except:
                print("Invalid Element for mob %s: %s" % (x.id, tmp))
                exit(1)
        elif "	Race:" in a:
            try:
                x.race=int(stp(a))
            except:
                print("Invalid Race for mob %s: %s" % (x.id, a))
                exit(1)
        elif 'Drops: ' in a:
            dropper=True
        elif dropper and '}' in a:
            dropper=False
        elif dropper:
            x.drops.append(stp(a).split(": "))
        elif "Plant: true" in a:
            skip=1
    # Write last entry
    MobAlloc(x)

    writeMob()

    wikib.write('\n\n|Mode|Desc|\n|----|----|\n')
    wikib.write('|Lot|Looter|\n')
    wikib.write('|Ass|Assist|\n')
    wikib.write('|Agr|Aggressive|\n')

    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('Name: ','').replace('Element: ','').replace('Race: ','').replace('AttackDelay: ', '').replace('WalkMask: ','').replace('MoveSpeed: ', '').replace('AttackRange: ', '').replace('ViewRange: ','').replace('Attack: ','').replace('ViewRange: ','').replace('Hp: ','').replace('Id: ','').replace('Lv: ','').replace('view range','').replace('attack range','').replace('move speed','').replace('health','').replace('(int','').replace('attack delay','atk.').replace('(','').replace(')','').replace('WALK_','').replace('Def: ','').replace('Mdef: ','')


def MonsterWrite(tbl):
    global skipCI
    # TODO: Check _mobs files to determine the usual monster density (a misc info to aid adding proper drop specs)
    wikib.write("<table border=1>\n")
    if stgen:
        wikib.write("<tr><th>ID</th><th>Name</th><th>Mob Info</th><th>Stgen</th><th>Elegen</th><th>Misc Info</th><th>Rewards</th><th>Stats</th><th>Drops</th></tr>\n")
    else:
        wikib.write("<tr><th>ID</th><th>Name</th><th>Mob Info</th><th>Elegen</th><th>Misc Info</th><th>Rewards</th><th>Stats</th><th>Drops</th></tr>\n")

    if not skipCI:
        tbl=sorted(tbl,  key=lambda tbl: int(tbl.mobpt))

    for i in tbl:
        if i.id == 'ID':
            continue

        # Special skips for REDESIGN
        #if (int(i.id) < 1187):
        #    continue
        if not bifs and ((int(i.hp) <= 50) or (i.race == 3)):
            continue

        if i.boss:
            i.name="<b>"+i.name+"</b>"
        if stgen:
            wikib.write('<tr><td><a name="' + i.id + '"></a>' +
                        i.id +"</td><td>"+
                        i.name +"</td><td>"+
                        mb_core(i) +"</td><td>"+
                        mbdt('advise',mb_stgen(i)) +"</td><td>"+
                        mb_eleg(i) +"</td><td>"+
                        mbdt('misc', mb_rdmisc(i)) +"</td><td>"+
                        mbdt('Exp\'s', mb_rdrw(i)) +"</td><td>"+
                        mbdt('stats', mb_rdstat(i)) +"</td><td>"+
                        mbdt('drops', mb_rddrop(i)) +"</td></tr>\n"
                        )
        else:
            wikib.write('<tr><td><a name="' + i.id + '"></a>' +
                        i.id +"</td><td>"+
                        i.name +"</td><td>"+
                        mb_core(i) +"</td><td>"+
                        mb_eleg(i) +"</td><td>"+
                        mbdt('misc', mb_rdmisc(i)) +"</td><td>"+
                        mbdt('Exp\'s', mb_rdrw(i)) +"</td><td>"+
                        mbdt('stats', mb_rdstat(i)) +"</td><td>"+
                        mbdt('drops', mb_rddrop(i)) +"</td></tr>\n"
                        )
    wikib.write("</table>\n")
    wikib.write("<b>Total: %02d Monsters</b><br/>\n" % len(tbl))
    wikib.write("\n<a href=#x>(↑) Return to top</a><br/><br/>\n\n")

def writeMob():
    wikib.write("<ul>\
<li><a href=#0>Starter</a></li>\n\
<li><a href=#1>Apprentice</a></li>\n\
<li><a href=#2>Intermediary</a></li>\n\
<li><a href=#3>Advanced</a></li>\n\
<li><a href=#4>Expert</a></li>\n\
<li><a href=#5>Master</a></li>\n\
<li><a href=#Nan>OoS</a></li>\n\
</ul>    ")

    wikib.write("<h1 id=0>Lv 0-20</h1>\n\n")
    MonsterWrite(Mobs1)
    wikib.write("<h1 id=1>Lv 21-40</h1>\n\n")
    MonsterWrite(Mobs2)
    wikib.write("<h1 id=2>Lv 41-60</h1>\n\n")
    MonsterWrite(Mobs3)
    wikib.write("<h1 id=3>Lv 61-80</h1>\n\n")
    MonsterWrite(Mobs4)
    wikib.write("<h1 id=4>Lv 81-100</h1>\n\n")
    MonsterWrite(Mobs5)
    wikib.write("<h1 id=5>Lv 101-150</h1>\n\n")
    MonsterWrite(Mobs6)

    wikib.write("<h1 id=NaN>Lv 101+</h1>\n\n")
    MonsterWrite(MobsA)


def mbdt(summary, content):
    return "<b>"+summary+"</b><br/><pre>"+content+"</pre>"
    return "<details>\
<summary>"+summary+"</summary>\
<pre>"+content+"</pre></details>"

def mb_core(mb):
    buff=""
    buff+="Lvl: %s<br/>\n" % (mb.mobpt)
    buff+="HP: <b><font color=#0a0>%s</font></b><br/>\n" % (mb.hp)
    buff+="ATK: <b><font color=#a00>%s</font></b><br/>\n" % (mb.atk)
    buff+="DEF: <b><font color=#775>%s/%s</font></b><br/>\n" % (mb.dfn, mb.mdf)
    if mb.st != "":
        buff+="Modes: <i>%s</i>" % (mb.st)
    return buff

def mb_eleg(mb):
    buff=""
    buff+="Race: %s<br/>\n" % (WhatRace(mb))
    buff+="Walk: %s<br/>\n" % (fwalk(mb.walk))
    buff+="Element: %s<br/>\n" % (WhatElem(mb))
    return buff

############################################################
def mb_stgen(mb):
    lv=int(mb.mobpt)
    st=int(mb.str.replace(' ', '').replace('Str:',''))
    #ag=int(mb.agi.replace(' ', '').replace('Agi:',''))
    vi=int(mb.vit.replace(' ', '').replace('Vit:',''))
    #it=int(mb.int.replace(' ', '').replace('Int:',''))
    #dx=int(mb.dex.replace(' ', '').replace('Dex:',''))
    #lk=int(mb.luk.replace(' ', '').replace('Luk:',''))

    # Attack Range vs Attack Delay
    ar=int(mb.range)
    ad=int(mb.delay)
    mv=int(mb.move)
    magr=False
    mass=False
    if ('Agr' in mb.st):
        magr=True
    if ('Ass' in mb.st):
        mass=True

    if (not ar):
        ar=1    

    # Fórmula do dano:
    # Tal que level 10 cause 150 dano
    # Tal que level 50 cause 1000 dano
    # Tal que a fórmula seja exponencial
    """
    lhp=lv**1.5+lv*(vi/100)+lv*15
    hhp=lv**1.8+lv*(vi/100)+lv*15
    # Casos especiais
    if mb.boss:
        lhp*=1.6
        hhp*=4.2
    if "slime" in mb.name.lower():
        lhp*=0.4
        hhp*=0.4
    if ar > 1:
        lhp-=ar**2
        hhp-=ar**2

    # Fórmula da HPTable: 400+(x*50)
    # MASTERED
    lat=(lv*40+lv**1.2+lv*(st/100))/ar
    hat=(lv*40+lv**1.5+lv*(st/100))/ar
    # Casos especiais
    if mb.boss:
        lat*=1.2
        hat*=1.4
    if "slime" in mb.name.lower():
        lat*=0.3
        hat*=0.3
    # Attack is DPS. So we must adjust to be a damage per second
    lat*=(ad/1872)
    hat*=(ad/1872)
    # Formula is not reliable
    lat/=2
    hat/=2
    # Consider Aggressive and Assist mobs
    if magr:
        lat*=0.8
        hat*=0.8
    if mass:
        lat*=0.9
        hat*=0.9

    # Experience
    lxp=(lv**1.2+lat+(lhp/8)) / max(1,(12-(lv/10)))
    hxp=(lv**1.6+hat+(hhp/8)) / max(1,(15-(lv/10)))
    # Casos especiais
    if mb.boss:
        lxp*=4.2
        hxp*=4.7
    """

    # Over100 Special Formula
    OVER100=0
    if lv > 100:
        OVER100=lv-100
        lv=100+OVER100*0.25

    # Fórmula da HPTable: 400+(x*50)
    # MASTERED
    lat=(lv*40+lv**1.2+lv*(st/100))
    hat=(lv*40+lv**1.5+lv*(st/100))
    if (ar > 1):
        lat*=max(0.5, 1.0-((ar-1)/10.0))
        hat*=max(0.5, 1.0-((ar-1)/10.0))

    # Casos especiais
    if mb.boss:
        lat*=1.2
        hat*=1.4
    if "slime" in mb.name.lower():
        lat*=0.3
        hat*=0.3
    # Attack is DPS. So we must adjust to be a damage per second
    lat*=(ad/1872)
    hat*=(ad/1872)
    # Formula is not reliable
    lat*=0.55
    hat*=0.55
    lat*=max(0.5, 1.0-(lv/10.0))
    hat*=max(0.5, 1.0-(lv/10.0))
    # Consider Aggressive and Assist mobs
    if magr:
        lat*=0.78
        hat*=0.78
    if mass:
        lat*=0.89
        hat*=0.89


    # Over100 Special Formula
    if OVER100:
        lv=100+OVER100*2

    # HP: Each 10 levels give you 100 extra weapon damage
    # I expect from 6 to 14 hits to kill
    # You deliver in average two hits per second
    # Mobs deliver one hit each four seconds (and that's 1hand advantage)
    lhp=lv*20*6+lv*(vi/100)
    hhp=lv*20*14+lv*(vi/100)
    if mb.boss:
        lhp*=1.4
        hhp*=1.8
    if "slime" in mb.name.lower():
        lhp*=0.6
        hhp*=0.6
    if ar > 1 and not OVER100:
        lhp*=0.9
        hhp*=0.9

    # Experience is way too non-linear and I prefer to do it with reference formula
    # like I was doing before
    # But let's use a formula based on mobs-to-lvl-up where you must kill 1580 lv 60 mobs
    # to raise from lv 60 (you can kill lv 50 mobs easier - but then I expect 3700 kills)
    # mobs to kill to raise level

    # This is the current mob-lvl-exp-table generated by this software
    # As you see, it is somewhat similar to TMW Org.
    # Remember aggressive, fast, and assistant mobs give even more exp

    # Level 1: total 1 mobs individual 3 xp (1.450)
    # Level 2: total 3 mobs individual 5 xp (1.450)
    # Level 3: total 8 mobs individual 5 xp (1.450)
    # Level 4: total 16 mobs individual 4 xp (1.450)
    # Level 5: total 26 mobs individual 7 xp (1.450)
    # Level 6: total 39 mobs individual 8 xp (1.450)
    # Level 7: total 56 mobs individual 9 xp (1.450)
    # Level 8: total 77 mobs individual 9 xp (1.450)
    # Level 9: total 101 mobs individual 10 xp (1.450)
    # Level 10: total 129 mobs individual 11 xp (1.450)
    # Level 20: total 667 mobs individual 21 xp (1.450)
    # Level 30: total 1767 mobs individual 57 xp (1.450)
    # Level 31: total 1912 mobs individual 63 xp (1.450)
    # Level 32: total 2064 mobs individual 68 xp (1.450)
    # Level 33: total 2223 mobs individual 73 xp (1.450)
    # Level 34: total 2390 mobs individual 84 xp (1.450)
    # Level 35: total 2563 mobs individual 91 xp (1.450)
    # Level 36: total 2747 mobs individual 96 xp (1.455)
    # Level 37: total 2942 mobs individual 101 xp (1.460)
    # Level 38: total 3148 mobs individual 105 xp (1.465)
    # Level 39: total 3366 mobs individual 130 xp (1.470)
    # Level 40: total 3597 mobs individual 148 xp (1.475)
    # Level 41: total 3841 mobs individual 156 xp (1.480)
    # Level 42: total 4098 mobs individual 163 xp (1.485)
    # Level 43: total 4369 mobs individual 170 xp (1.490)
    # Level 44: total 4656 mobs individual 185 xp (1.495)
    # Level 45: total 4958 mobs individual 193 xp (1.500)
    # Level 46: total 5276 mobs individual 201 xp (1.505)
    # Level 47: total 5611 mobs individual 208 xp (1.510)
    # Level 48: total 5963 mobs individual 215 xp (1.515)
    # Level 49: total 6334 mobs individual 249 xp (1.520)
    # Level 50: total 6724 mobs individual 295 xp (1.525)
    # Level 51: total 7133 mobs individual 314 xp (1.530)
    # Level 52: total 7564 mobs individual 331 xp (1.535)
    # Level 53: total 8016 mobs individual 348 xp (1.540)
    # Level 54: total 8491 mobs individual 375 xp (1.545)
    # Level 55: total 8990 mobs individual 393 xp (1.550)
    # Level 56: total 9512 mobs individual 411 xp (1.555)
    # Level 57: total 10061 mobs individual 428 xp (1.560)
    # Level 58: total 10636 mobs individual 443 xp (1.565)
    # Level 59: total 11239 mobs individual 514 xp (1.570)
    # Level 60: total 11871 mobs individual 579 xp (1.575)
    # Level 61: total 12533 mobs individual 608 xp (1.580)
    # Level 62: total 13226 mobs individual 638 xp (1.585)
    # Level 63: total 13952 mobs individual 670 xp (1.590)
    # Level 64: total 14712 mobs individual 704 xp (1.595)
    # Level 65: total 15508 mobs individual 740 xp (1.600)
    # Level 66: total 16340 mobs individual 778 xp (1.605)
    # Level 67: total 17211 mobs individual 818 xp (1.610)
    # Level 68: total 18122 mobs individual 861 xp (1.615)
    # Level 69: total 19075 mobs individual 905 xp (1.620)
    # Level 70: total 20071 mobs individual 952 xp (1.625)
    # Level 80: total 32389 mobs individual 1783 xp (1.650)
    # Level 90: total 47806 mobs individual 3635 xp (1.650)
    # Level 100: total 66308 mobs individual 4976 xp (1.650)

    # Over100 Special Formula
    if OVER100:
        lv=100+OVER100

    try:
        mxp=exp[lv]
        hxp=exp[lv]
        lxp=exp[lv-1]
        minxp=exp[lv-1]
    except:
        mxp=exp[len(exp)-1]
        hxp=exp[len(exp)-1]
        lxp=exp[len(exp)-2]
        minxp=exp[len(exp)-2]
        print("Warning: Invalid exp for mob \033[1m%s\033[0m" % (mb.name.replace("<b>", "").replace("</b>", "")))

    if not mb.boss:
        if lv > 35:
            fx=1.45+((lv-35)/200.0)
        else:
            fx=1.45
        if fx > 1.65:
            fx=1.65

        # Aggressive, assistant and fast mobs yield more exp
        # Slow monsters yield less exp, because they're easier to kill on any playstyle
        if magr:
            fx-=0.09
        else:
            fx-=0.04
        if mass:
            fx-=0.08
        if mv < 200:
            fx-=0.02
        if mv > 500:
            fx+=0.02

        # 1 ^ anything = 1, so we need a better rule
        if lv != 1:
            lxp=minxp/(lv**fx)
        else:
            lxp=3 # 3~5 is fine
    # Boss are BOSS. It gives roughly 0.1% ~ 10.0% from lvlup xp.
    else:
        lxp=mxp/1000
        hxp=mxp/10
    del minxp, mxp

    # Over100 Special Formula (kinda)
    olv=0
    if lv > 80:
        olv=lv+0
        lv=80+(lv-80)*0.25

    # Defense follows the same player formula
    dfn=((lv**1.255)*2.5)
    dfn=dfn*350.0/810.0
    mdf=max(0, lv-5)+(lv/10.0)
    if not mb.boss:
        mdf/=2
    if ar > 3:
        dfn/=2

    # Nerf mobs def in 50% (to be more realistic to what we have)
    dfn/=2

    # Over100 Special Formula
    if OVER100:
        lv=100+OVER100
    else:
        lv=olv+0
    del olv

    # Force HP to be higher
    # It'll only start applying from level 40 onwards
    # It gives a bonus of 0.5% HP per mob level
    # This means a level 100 mob got 60 times that stronger: 30%
    if lv > 40:
        lhp=lhp*(1.0+((lv-40)/210.0))
        lhp=int(lhp)

    # Norm
    lhp=int(lhp)
    hhp=int(hhp)
    lat=int(lat)
    hat=int(hat)
    lxp=int(lxp)
    hxp=int(hxp)
    dfn=int(dfn)
    mdf=int(mdf)

    buff="<pre><font size=-2px>"
    buff+="HP Range: %s ~ %s<br/>\n" % (lhp, hhp)
    buff+="ATK Range: %s ~ %s<br/>\n" % (lat, hat)
    buff+="Maximum XP: %s ~ %s<br/>\n" % (lxp, hxp)
    buff+="DEF: %s / %s<br/>\n" % (dfn, mdf)
    buff+="<b>Drop, Move, Elegen, aspd<br/>\n"
    buff+="</b></font></pre>"
    return buff

def mb_rdstat(mb):
    buff="<pre><font size=-4px>"
    buff+="%s\n" % (mb.str)
    buff+="%s\n" % (mb.agi)
    buff+="%s\n" % (mb.vit)
    buff+="%s\n" % (mb.int)
    buff+="%s\n" % (mb.dex)
    buff+="%s\n" % (mb.luk)
    buff+="</font></pre>"
    return buff

def mb_rdmisc(mb):
    buff=""
    if "agr" in mb.st.lower():
        buff+="View Range: %s\n" % (mb.view)
    buff+="Attack Range: %s\n" % (mb.range)
    buff+="AtkDelay: %s ms\n" % (mb.delay)
    buff+="Move speed: %s ms\n" % (mb.move)
    buff+="Element Level: %d\n" % (mb.elel)
    return buff

def mb_rdrw(mb):
    buff=""
    buff+="<font color=#060><u>%s</b></u></font>\n" % (mb.xp.replace(' ', ' <b>'))
    buff+="<font color=#006><u>%s</b></u></font>\n" % (mb.jp.replace(' ', ' <b>'))
    try:
        buff+="MobPoints: %d\n" % (int(mb.mobpt)*11/10)
    except:
        pass
    return buff

def mb_rddrop(mb):
    buff=""
    tdr=0
    for ax in mb.drops:
        # Ignore disabled drops
        if ax[0].startswith("//"):
            continue

        # Write drop
        try:
            buff+=ax[0]+': ' + str(int(ax[1])/100.0) + ' %\n'
            tdr+=int(ax[1])
        except IndexError:
            print("Fatal: invalid %s mob with %s drops" % (mb.name, str(ax)))
            exit(1)
        except:
            print("[Warning] %s incorrect drop: %s" % (mb.name, str(ax)))
            buff+=ax[0]+': ' + ax[1] + ' ppm\n'

        # Save to SysDrops
        SysDrops.append([ax[0], ax[1], mb.name])

    if tdr < 500:
        print("[INFO] %s has %d/500 drops. Disqualified for Realm of Drops." % (mb.name, tdr))
    return buff



showHeader()

testMobs()

wikib.write('<br/><hr/>')
wikib.write("Run at: " + datetime.datetime.now().isoformat())
wikib.write('<hr/>')

wikib.write("""
<b>Player Stats (melee warrior)</b>
<table border=1>
<tr><th>Level</th><th>Stats 1</th><th>Stats 2</th><th>Average</th></tr>

<tr><th>00</th>
<td>str: 2 agi: 5 vit: 7 int:1 dex: 6 luk: 3</td>
<td>str: 2 agi: 5 vit: 7 int:1 dex: 6 luk: 3</td>
<th>str: 2 agi: 5 vit: 7 int:1 dex: 6 luk: 3</th></tr>

<tr><th>10</th>
<td>str:15 agi:10 vit: 5 int:1 dex:10 luk: 4</td>
<td>str:11 agi:11 vit: 6 int:1 dex:11 luk: 7</td>
<th>str:13 agi:11 vit: 5 int:1 dex:10 luk: 6</th></tr>

<tr><th>20</th>
<td>str:19 agi:10 vit:10 int:1 dex:20 luk:10</td>
<td>str:14 agi:19 vit: 8 int:1 dex:17 luk:11</td>
<th>str:17 agi:14 vit: 9 int:1 dex:18 luk:11</th></tr>

<tr><th>30</th>
<td>str:25 agi:30 vit:10 int:1 dex:20 luk:10</td>
<td>str:22 agi:28 vit:12 int:1 dex:21 luk:15</td>
<th>str:24 agi:29 vit:11 int:1 dex:20 luk:13</th></tr>

<tr><th>40</th>
<td>str:38 agi:30 vit:20 int:1 dex:25 luk:17</td>
<td>str:28 agi:35 vit:14 int:1 dex:32 luk:21</td>
<th>str:33 agi:33 vit:17 int:1 dex:28 luk:19</th></tr>

<tr><th>50</th>
<td>str:50 agi:40 vit:30 int:1 dex:25 luk:18</td>
<td>str:41 agi:41 vit:15 int:1 dex:41 luk:26</td>
<th>str:46 agi:41 vit:22 int:1 dex:33 luk:27</th></tr>

<tr><th>60</th>
<td>str:54 agi:50 vit:40 int:1 dex:35 luk:20</td>
<td>str:52 agi:52 vit:16 int:1 dex:45 luk:32</td>
<th>str:53 agi:51 vit:28 int:1 dex:40 luk:26</th></tr>

<tr><th>70</th>
<td>str:60 agi:60 vit:43 int:1 dex:50 luk:20</td>
<td>str:61 agi:61 vit:22 int:1 dex:51 luk:38</td>
<th>str:60 agi:61 vit:33 int:1 dex:50 luk:29</th></tr>

<tr><th>80</th>
<td>str:80 agi:60 vit:50 int:1 dex:50 luk:25</td>
<td>str:65 agi:71 vit:32 int:1 dex:60 luk:41</td>
<th>str:72 agi:66 vit:41 int:1 dex:55 luk:33</th></tr>

<tr><th>90</th>
<td>str:80 agi:70 vit:60 int:1 dex:60 luk:31</td>
<td>str:71 agi:71 vit:41 int:1 dex:71 luk:51</td>
<th>str:76 agi:70 vit:50 int:1 dex:66 luk:41</th></tr>

<tr><th>100</th>
<td>str:90 agi:80 vit:69 int:1 dex:60 luk:31</td>
<td>str:71 agi:81 vit:42 int:1 dex:81 luk:61</td>
<th>str:81 agi:80 vit:56 int:1 dex:70 luk:46</th></tr>

<tr><th>110</th>
<td>str:90 agi:90 vit:69 int:1 dex:70 luk:35</td>
<td>str:82 agi:82 vit:50 int:1 dex:82 luk:65</td>
<th>str:86 agi:86 vit:60 int:1 dex:76 luk:50</th></tr>

<tr><th>120</th>
<td>str:99 agi:90 vit:69 int:1 dex:70 luk:45</td>
<td>str:86 agi:86 vit:51 int:1 dex:86 luk:68</td>
<th>str:93 agi:88 vit:60 int:1 dex:78 luk:56</th></tr>

<tr><th>130</th>
<td>str:99 agi:91 vit:75 int:1 dex:70 luk:55</td>
<td>str:91 agi:90 vit:51 int:1 dex:90 luk:68</td>
<th>str:95 agi:91 vit:63 int:1 dex:80 luk:61</th></tr>

</table>
""")
wikib.write('<hr/>')
wikib.write("""
<h3>Elemental Count</h3>
<table border=1>
<tr><td>%s</td><td>%02d</td></tr>
<tr><td>%s</td><td>%02d</td></tr>
<tr><td>%s</td><td>%02d</td></tr>
<tr><td>%s</td><td>%02d</td></tr>
<tr><td>%s</td><td>%02d</td></tr>
<tr><td>%s</td><td>%02d</td></tr>
<tr><td>%s</td><td>%02d</td></tr>
<tr><td>%s</td><td>%02d</td></tr>
<tr><td>%s</td><td>%02d</td></tr>
</table>
""" % (
"Neutral", Ele[0],
"Water", Ele[1],
"Earth", Ele[2],
"Fire", Ele[3],
"Wind", Ele[4],
"Holy", Ele[6],
"Dark", Ele[7],
"Ghost", Ele[8],
"Error", Ele[5]))

wikib.write('</body></html>')
wikib.close()
#print(str(SysDrops))

# Aeros allocation
if aeros:
    print("// These arrays are filled automatically by redesign.py");
    print("setarray .ML_Plants, "+
    str(Plants).replace('[','').replace(']','').replace("'","")+";")
    print("setarray .ML_Boss, "+
    str(Boss).replace('[','').replace(']','').replace("'","")+";")
    print("setarray .ML_Aggr, "+
    str(Aggressive).replace('[','').replace(']','').replace("'","")+";")
    print("setarray .ML_Asst, "+
    str(Assistant).replace('[','').replace(']','').replace("'","")+";")
    print("setarray .ML_Loot, "+
    str(Looter).replace('[','').replace(']','').replace("'","")+";")
    print("setarray .ML_Lv50, "+
    str(Level50).replace('[','').replace(']','').replace("'","").replace('ID, ','')+
    ";")
    print("setarray .ML_Lv99, "+
    str(Level100).replace('[','').replace(']','').replace("'","")+";")

showFooter()
exit(0)