All below calculations assume the following:
- Base level of 150 (unless stated otherwise)
- Basic attack of 400
- Mastery of 60%
- Include elemental staves (if the player has them) and Elemental Amplification (KMS values)
Introduction:
Welcome to the ultimate magician damage scaling thread! This thread is largely different from all other threads because it calculates your REAL magician’s damage. This is because the magic damage formula is known and extremely accurate.
It can often be difficult to tell, “Whose mage is better?” Every mage has different elemental weapons, skills, and base attacks available, and thus there is no clear cut way to say “My mage is strong.” This topic will remedy this problem.
How the calculation is performed:
By receiving statistics from you about your level, INT, and MATK, I can calculate your damage. To calculate the damage, I assume a basic attack of 400 and 60% mastery. At no point during the calculations do I check for the damage cap, so this is not an issue. Also, I assume that the person is at level 150 who allocates all points to INT (also accounting for job advancements), as is common among most “best damage” threads. Lastly, the Damage Amplification used for this topic assumes the new Amplification multipliers from KMS in which, at level 30, is a 40% boost instead of 35%.
Credit to everyone in Russt’s thread for figuring out the damage formula.
My theory on what bonuses should count is very simple – if the bonus shows in the upper right corner of your screen while used, the bonus will not be counted for this calculation. This rules out Meditation, pots, Maple Hero, etc. while also allowing elemental staves and amplification. If you happen to use Maple Warrior to equip your wand/staff, include the LUK from MW to equip the wand/staf but not the INT as to not affect the damage calculation.
The source that I use is open and freely usable by anyone in the public. If you see any corrections that need to be made in the source, please let me know.
Source Code
Mage.py
Code:
class Mage:
def __init__(self):
self.IGN = ''
self.Class = -1
self.Level = -1
self.INT = -1
self.MATK = -1
self.MaxDamage = 0
self.MinDamage = 0
self.EleWand = 0
self.BasicAttack = 400
self.Mastery = 0.6
self.AmpLevel = 0
self.AmpLevels = [100, 107, 109, 111, 113, 114, 115, 116, 117, 118,
119, 121, 121, 123, 123, 125, 125, 127, 127, 129, 129,
131, 131, 133, 133, 135, 135, 137, 137, 137, 140]
self.AmpMultiplier = 1.00
#Level from which all calculations will be made
self.BaseLevel = 150
def AssignAmpLevel(self, AmpLevel):
if self.IsCleric():
raise Exception("AssignAmpLevel: Cleric/Priest/Bishop class does not have Amp -> %s" % (self.IGN))
if self.IsSecondJob() and AmpLevel > 0:
raise Exception("AssignAmpLevel: Must be third job to allocate points to Amp -> %s" % (self.IGN))
if AmpLevel > ((self.Level - 70) * 3) + 1:
raise Exception("AssignAmpLevel: Level of Amp impossible with level -> %s" % (self.IGN))
self.AmpLevel = AmpLevel
self.AmpMultiplier = self.AmpLevels[AmpLevel] / 100
def __CalculateAdditionalINT(self):
if self.Level == -1:
raise Exception("CalculateAdditionalINT: Level must have a parameter -> %s" % (self.IGN))
if self.INT == -1:
raise Exception("CalcualteAdditionalINT: INT must have a parameter -> %s" % (self.IGN))
if self.MATK == -1:
raise Exception("CalculateAdditionalINT: MATK must have a parameter -> %s" % (self.IGN))
if self.Class == -1:
raise Exception("CalculateAdditionalINT: Class must have a parameter -> %s" % (self.IGN))
#Level difference assumes all points put into INT
INTToAdd = (self.BaseLevel - self.Level) * 5
#Job Advancement
ExtraINT = (2 - (self.Class % 10)) * 5
INTToAdd += ExtraINT
self.INT += INTToAdd
#INT adds to MATK too
self.MATK += INTToAdd
if self.MATK > 1999:
self.MATK = 1999
self.Level = 150
def CalculateDamage(self, Type='Adjust'):
if Type == 'Adjust':
if self.Level is not 150:
self.__CalculateAdditionalINT()
if Type == 'NoAdjust':
self.AmpMultiplier = 1.00
if self.IsCleric() and self.EleWand == 1:
raise Exception("CalculateDamage: Cleric class does not have elemental weapons -> %s" % (self.IGN))
if self.Level < 70 and self.EleWand == 1:
raise Exception("CalculateDamage: Elemental wands are for level 70 and up -> %s" % (self.IGN))
self.MaxDamage = (((self.MATK ** 2) / 1000 + self.MATK) / 30 + self.INT/200) * self.BasicAttack * self.AmpMultiplier
self.MinDamage = (((self.MATK ** 2) / 1000 + self.MATK * self.Mastery * 0.9)/30 + self.INT/200) * self.BasicAttack * self.AmpMultiplier
if(self.EleWand == 1) and Type == 'Adjust':
self.MaxDamage *= 1.25
self.MinDamage *= 1.25
self.MaxDamage = int(self.MaxDamage)
self.MinDamage = int(self.MinDamage)
def IsCleric(self):
if (230 <= self.Class <= 232):
return True
return False
def IsIL(self):
if (220 <= self.Class <= 222):
return True
return False
def IsFP(self):
if (210 <= self.Class <= 212):
return True
return False
def IsSecondJob(self):
if self.Class % 10 == 0:
return True
return False
def IsThirdJob(self):
if self.Class % 10 == 1:
return True
return False
def IsFourthJob(self):
if self.Class % 10 == 2:
return True
return False
PlayerReader.py
Code:
import configparser
import os
import Mage
Bishops = []
ILArchMage = []
FPArchMage = []
Levels = []
def Main():
config = configparser.SafeConfigParser()
config.readfp(open('Players.txt'))
sections = config.sections()
for Name in sections:
items = config.items(Name)
MyMage = Mage.Mage()
MyMage.IGN = Name
for key, value in items:
if key == 'level':
MyMage.Level = int(value)
elif key == 'class':
MyMage.Class = int(value)
elif key == 'int':
MyMage.INT = int(value)
elif key == 'matk':
MyMage.MATK = int(value)
elif key == 'amp level':
MyMage.AssignAmpLevel(int(value))
elif key == 'elemental staff?':
MyMage.EleWand = int(value)
elif key == 'link':
MyMage.Link = value
MyMage.CalculateDamage('NoAdjust')
Levels.append([MyMage.Level, MyMage.IGN, MyMage.INT, MyMage.MATK,
MyMage.MinDamage, MyMage.MaxDamage, MyMage.Link])
MyMage.CalculateDamage()
if 230 <= MyMage.Class <= 232:
Bishops.append([MyMage.MinDamage, MyMage.MaxDamage, MyMage.Level,
MyMage.INT, MyMage.MATK, MyMage.IGN, MyMage.Link])
if 220 <= MyMage.Class <= 222:
ILArchMage.append([MyMage.MinDamage, MyMage.MaxDamage, MyMage.Level,
MyMage.INT, MyMage.MATK, MyMage.IGN, MyMage.Link])
if 210 <= MyMage.Class <= 212:
FPArchMage.append([MyMage.MinDamage, MyMage.MaxDamage, MyMage.Level,
MyMage.INT, MyMage.MATK, MyMage.IGN, MyMage.Link])
if os.access('OutputTable.txt', os.F_OK):
os.unlink('OutputTable.txt')
CreateTable(Bishops, 'Cleric/Priest/Bishop')
CreateTable(ILArchMage, 'I/L Mages')
CreateTable(FPArchMage, 'F/P Mages')
CreateTableLevels(Levels, 'Without level adjustments and Archmage buffs...')
def CreateTableLevels(Levels, Header):
if Levels != []:
MyTable = Table(Header, 'Damage')
Levels.sort()
Levels.reverse()
for EachPlayer in Levels:
Level, IGN, INT, MATK, Min, Max, Link = EachPlayer
MyTable.AddRow(IGN, Level, INT, MATK, Min, Max, Link)
MyTable.Flush()
def CreateTable(List, Header):
if List != []:
MyTable = Table(Header)
#sorts according to minimum damage
List.sort()
List.reverse()
for EachPlayer in List:
Min, Max, Level, INT, MATK, IGN, Link = EachPlayer
MyTable.AddRow(IGN, Level, INT, MATK, Min, Max, Link)
MyTable.Flush()
class Table:
def __init__(self, Header, BaseLevel='Damage at 150'):
self.TableFile = 'OutputTable.txt'
self.SpoilerAdded = 0
self.Table = self.AddSpoiler(Header)
self.BaseLevel = BaseLevel
self.InitializeTable()
def AddSpoiler(self, Header):
self.SpoilerAdded = 1
return '
Requirements:
1. You must be at least second job or higher to apply
2. You must post a screenshot of your entire stat window.
3. If you will be claiming that you have an elemental staff, you must be an f/p or i/l mage and post your inventory showing that you have it equipped.
If you are a cleric/priest/bishop, please fill out the following form:
[b]IGN:[/b]
[b]Class:[/b]
[b]Level:[/b]
[b]INT:[/b]
[b]MATK:[/b]
Otherwise, please fill out the following form:
[b]IGN:[/b]
[b]Class:[/b]
[b]Level:[/b]
[b]INT:[/b]
[b]MATK:[/b]
[b]Amp Level:[/b]
[b]Elemental Staff?:[/b]
For “Elemental Staff?”, please put a “1” if you have one and “0” if you do not.
Here's a hypothetical example of what I'm looking for:
There will be three spoilers, one for each branch of mages. In each spoiler, I will calculate the minimum and maximum damage of each mage and rank them from highest to lowest according to minimum damage.
In the final spoiler, “Levels”, all bonuses given to archmages are removed. This puts all three branches of the mage class on a very even playing field. Then the table is sorted according to descending level. This way you can compare how your damage ranks with your peers.
(this is with the assumption that I get a clean blue dragon staff and egg my HTP, in addition to using maxed MW to equip the 163 staff)
IGN: Harrisonized
Class: F/P ArchMage
Level: 163
INT: 899 (730+96+73) <~ the +73 is from MW, but pulled out...
LUK: 165 (107+48+10) <~ the +10 is from MW, but pulled out... LUK is irrelevant but just showing how I got there.
MATK: 1107 <~ This includes the MW.
Amp Level: 30
Elemental Staff?: 1
Since MW is involved, how would you pull out MW properly?
Last edited by Harrisonized; 2009-04-12 at 06:41 AM.
(this is with the assumption that I get a clean blue dragon staff and egg my HTP, in addition to using maxed MW to equip the 163 staff)
IGN: Harrisonized
Class: F/P ArchMage
Level: 163
INT: 899 (730+96+73) <~ the +73 is from MW, but pulled out...
LUK: 165 (107+48+10) <~ the +10 is from MW, but pulled out... LUK is irrelevant but just showing how I got there.
MATK: 1107 <~ This includes the MW.
Amp Level: 30
Elemental Staff?: 1
Since MW is involved, how would you pull out MW properly?
I'd likely include the LUK for Maple Warrior since you use it to equip the staff, but I would not include the Maple Warrior stats from INT, so subtract out the 73 from INT & MATK and leave the LUK in since LUK won't affect the table at all.
EDIT: Kabanaw, I just noticed you are using Meditation to reach that MATK value. Meditation isn't allowed since the buff appears in the upper-right corner. I will adjust the table without the MATK boost.
I'd likely include the LUK for Maple Warrior since you use it to equip the staff, but I would not include the Maple Warrior stats from INT, so subtract out the 73 from INT & MATK and leave the LUK in since LUK won't affect the table at all.
EDIT: Kabanaw, I just noticed you are using Meditation to reach that MATK value. Meditation isn't allowed since the buff appears in the upper-right corner. I will adjust the table without the MATK boost.
Just now, I found AAA batteries for my graphing calculator and noticed that my RAM cleared. So the first thing I thought of doing was checking my damage.
I reprogrammed the MATK damage back into my calculator (by hand) and then compared the values with the ones in your table. ALL of your values are incorrect because you forgot to give all of the mages (nonbishops) AMP.
AMP is a 1.35x raw bonus, given the same way as the bonus from the Elemental boost is.
>_>
~~~~~
A few things I think you need to clean up your thread.
You said "This way you can compare how your damage ranks with your peers."
The way you set up that last table wouldn't help you compare with your peers. It's just taking out factors to make a comparison between matk scores and int.
1) For the last spoiler, include amp and elementals. Your table should look something like this:
IGN - Level Damage - INT - MATK - Job - AMP - Elemental
2) Include the above, but locked at level 150.
3) Use 570 for Arch mages and 670 for Bishops.
I think that it would only be fair to include these "other factors". The truth is that Bishops are a "different" class from Mages (even grendel the very old said so if you read his quests), they should be considered that way when calculating damage.
The only real attack that Mages share are their ultimates. Otherwise, you could use the base damage for Big Bang, which wouldn't work because then the Elemental Staves wouldn't be factored in. The multiplier should represent something meaningful, not just some random number pulled out of the blue.
AMP should never be taken out. AMP is a permanent change in a magician, and it should be factored in comparisons because it's purely from your character. It's what separates magicians from bishops.
Elemental staves were designed for Mages. Consider that a lot of bishops have elemental wands, but they can't utilize it's bonus. Why should a mage holding an elemental wand be considered the same as a Bishop holding the same wand?
Bishops' genesis are just different altogether. They're faster, they're not AMPed. But nonetheless, they should be 100 higher just as in game. If not, then almost ALL of the mages, regardless of lukless or luk would completely trump the Bishop's projected damage.
Include elemental type. A FP mage holding a Poison Staff isn't going to be dealing as much damage using a Fire Staff for Meteo. In addition, the primary staves are always more expensive than the secondaries. Ice staves are obviously more expensive than thunder staves. If this truly is a damage comparison based on the equips we have, buying a thunder staff isn't going to cut it. People spend money upgrading each and every equip. Buying a thunder staff and saying you have as much power as someone with a ice staff is almost cheating your score. >_>
These factors play an important role in the game, hence, should be added in.
~~~~~
Originally Posted by Fiel
I'd likely include the LUK for Maple Warrior since you use it to equip the staff, but I would not include the Maple Warrior stats from INT, so subtract out the 73 from INT & MATK and leave the LUK in since LUK won't affect the table at all.
Yes, but you'd be "subtracting levels". The staff I intend to wear is level 163. By subtracting down to 150, I believe we will run into some kind of loophole. I won't have enough LUK at 150. I plan to add luk in when I near 163. I also will be wearing my crappy staves which wouldn't work either because that'd give me a significantly lower score.
~~~~~
Originally Posted by Fiel
Source Code
Mage.py
Code:
class Mage:
def __init__(self):
self.IGN = ''
self.Class = -1
self.Level = -1
self.INT = -1
self.MATK = -1
self.MaxDamage = 0
self.MinDamage = 0
self.EleWand = 0
self.BasicAttack = 400
self.Mastery = 0.6
self.AmpLevel = 0
self.AmpLevels = [100, 107, 109, 111, 113, 114, 115, 116, 117, 118,
119, 121, 121, 123, 123, 125, 125, 127, 127, 129, 129,
131, 131, 133, 133, 135, 135, 137, 137, 137, 140]
self.AmpMultiplier = 1.00
#Level from which all calculations will be made
self.BaseLevel = 150
def AssignAmpLevel(self, AmpLevel):
if self.IsCleric():
raise Exception("AssignAmpLevel: Cleric/Priest/Bishop class does not have Amp -> %s" % (self.IGN))
if self.IsSecondJob() and AmpLevel > 0:
raise Exception("AssignAmpLevel: Must be third job to allocate points to Amp -> %s" % (self.IGN))
if AmpLevel > ((self.Level - 70) * 3) + 1:
raise Exception("AssignAmpLevel: Level of Amp impossible with level -> %s" % (self.IGN))
self.AmpLevel = AmpLevel
self.AmpMultiplier = self.AmpLevels[AmpLevel] / 100
def __CalculateAdditionalINT(self):
if self.Level == -1:
raise Exception("CalculateAdditionalINT: Level must have a parameter -> %s" % (self.IGN))
if self.INT == -1:
raise Exception("CalcualteAdditionalINT: INT must have a parameter -> %s" % (self.IGN))
if self.MATK == -1:
raise Exception("CalculateAdditionalINT: MATK must have a parameter -> %s" % (self.IGN))
if self.Class == -1:
raise Exception("CalculateAdditionalINT: Class must have a parameter -> %s" % (self.IGN))
#Level difference assumes all points put into INT
INTToAdd = (self.BaseLevel - self.Level) * 5
#Job Advancement
ExtraINT = (2 - (self.Class % 10)) * 5
INTToAdd += ExtraINT
self.INT += INTToAdd
#INT adds to MATK too
self.MATK += INTToAdd
if self.MATK > 1999:
self.MATK = 1999
self.Level = 150
def CalculateDamage(self, Type='Adjust'):
if Type == 'Adjust':
if self.Level is not 150:
self.__CalculateAdditionalINT()
if Type == 'NoAdjust':
self.AmpMultiplier = 1.00
if self.IsCleric() and self.EleWand == 1:
raise Exception("CalculateDamage: Cleric class does not have elemental weapons -> %s" % (self.IGN))
if self.Level < 70 and self.EleWand == 1:
raise Exception("CalculateDamage: Elemental wands are for level 70 and up -> %s" % (self.IGN))
self.MaxDamage = (((self.MATK ** 2) / 1000 + self.MATK) / 30 + self.INT/200) * self.BasicAttack * self.AmpMultiplier
self.MinDamage = (((self.MATK ** 2) / 1000 + self.MATK * self.Mastery * 0.9)/30 + self.INT/200) * self.BasicAttack * self.AmpMultiplier
if(self.EleWand == 1) and Type == 'Adjust':
self.MaxDamage *= 1.25
self.MinDamage *= 1.25
self.MaxDamage = int(self.MaxDamage)
self.MinDamage = int(self.MinDamage)
def IsCleric(self):
if (230 <= self.Class <= 232):
return True
return False
def IsIL(self):
if (220 <= self.Class <= 222):
return True
return False
def IsFP(self):
if (210 <= self.Class <= 212):
return True
return False
def IsSecondJob(self):
if self.Class % 10 == 0:
return True
return False
def IsThirdJob(self):
if self.Class % 10 == 1:
return True
return False
def IsFourthJob(self):
if self.Class % 10 == 2:
return True
return False
PlayerReader.py
Code:
import configparser
import os
import Mage
Bishops = []
ILArchMage = []
FPArchMage = []
Levels = []
def Main():
config = configparser.SafeConfigParser()
config.readfp(open('Players.txt'))
sections = config.sections()
for Name in sections:
items = config.items(Name)
MyMage = Mage.Mage()
MyMage.IGN = Name
for key, value in items:
if key == 'level':
MyMage.Level = int(value)
elif key == 'class':
MyMage.Class = int(value)
elif key == 'int':
MyMage.INT = int(value)
elif key == 'matk':
MyMage.MATK = int(value)
elif key == 'amp level':
MyMage.AssignAmpLevel(int(value))
elif key == 'elemental staff?':
MyMage.EleWand = int(value)
elif key == 'link':
MyMage.Link = value
MyMage.CalculateDamage('NoAdjust')
Levels.append([MyMage.Level, MyMage.IGN, MyMage.INT, MyMage.MATK,
MyMage.MinDamage, MyMage.MaxDamage, MyMage.Link])
MyMage.CalculateDamage()
if 230 <= MyMage.Class <= 232:
Bishops.append([MyMage.MinDamage, MyMage.MaxDamage, MyMage.Level,
MyMage.INT, MyMage.MATK, MyMage.IGN, MyMage.Link])
if 220 <= MyMage.Class <= 222:
ILArchMage.append([MyMage.MinDamage, MyMage.MaxDamage, MyMage.Level,
MyMage.INT, MyMage.MATK, MyMage.IGN, MyMage.Link])
if 210 <= MyMage.Class <= 212:
FPArchMage.append([MyMage.MinDamage, MyMage.MaxDamage, MyMage.Level,
MyMage.INT, MyMage.MATK, MyMage.IGN, MyMage.Link])
if os.access('OutputTable.txt', os.F_OK):
os.unlink('OutputTable.txt')
CreateTable(Bishops, 'Cleric/Priest/Bishop')
CreateTable(ILArchMage, 'I/L Mages')
CreateTable(FPArchMage, 'F/P Mages')
CreateTableLevels(Levels, 'Without level adjustments and Archmage buffs...')
def CreateTableLevels(Levels, Header):
if Levels != []:
MyTable = Table(Header, 'Damage')
Levels.sort()
Levels.reverse()
for EachPlayer in Levels:
Level, IGN, INT, MATK, Min, Max, Link = EachPlayer
MyTable.AddRow(IGN, Level, INT, MATK, Min, Max, Link)
MyTable.Flush()
def CreateTable(List, Header):
if List != []:
MyTable = Table(Header)
#sorts according to minimum damage
List.sort()
List.reverse()
for EachPlayer in List:
Min, Max, Level, INT, MATK, IGN, Link = EachPlayer
MyTable.AddRow(IGN, Level, INT, MATK, Min, Max, Link)
MyTable.Flush()
class Table:
def __init__(self, Header, BaseLevel='Damage at 150'):
self.TableFile = 'OutputTable.txt'
self.SpoilerAdded = 0
self.Table = self.AddSpoiler(Header)
self.BaseLevel = BaseLevel
self.InitializeTable()
def AddSpoiler(self, Header):
self.SpoilerAdded = 1
return '
Bookmarks