TL DR:
Against turrets:
- Cannon minions are the best when promoted+baron, and
about equally good as melee when they only have promote.
- Caster minions perform the worse when promoted, or promoted+baron.
Against minions:
- Melee are the best with promote, or promote+baron.
- Cannons with promote+baron are the worse (because baron reduces their attack speed by 50%).
Full answer
[...] it should be fairly trivial to calculate total offensive stats and final dps of a minion.
Not really. It can be quite complex.
Minions get a different bonus from baron and promote based on whether they are melee, casters, or cannons. To check which one deals more damage per second (dps) we will ignore how long they survive (obviously a ranged cannon would take less damage from enemies than a melee minion).
To do so, we multiply their total attack damage by their final attack speed. Then we apply multiplicative bonuses. Minions deal bonus damage to towers, and have a penalty on champions (but champions aren't examined in this answer).
Any damage reductions (e.g. armor, magic resist, etc) are disregarded, so dps values below are unmitigated. Lastly, game time is set to 30.
The results are:
=======================================================================
Minion: caster
----------------------------------------
VS turrets
promote
DPS: 154.2
Baron + promote
DPS: 180.3
----------------------------------------
VS minions
promote
DPS: 102.8
Baron + promote
DPS: 120.2
========================================================================
Minion: melee
----------------------------------------
VS turrets
promote
DPS: 256.5
Baron + promote
DPS: 256.5
----------------------------------------
VS minions
promote
DPS: 171.0
Baron + promote
DPS: 299.2
===========================================================================
Minion: siege
----------------------------------------
VS turrets
promote
DPS: 254.2
Baron + promote
DPS: 329.2
----------------------------------------
VS minions
promote
DPS: 169.5
Baron + promote
DPS: 109.8
This is the Python 3.4 code I wrote and used for above results:
raw_minion_stats = dict(
caster=dict(
att_dmg=23,
att_dmg_per_90_sec=1,
att_speed=0.670,
multiplicative_dmg_bonus_vs_turrets=1.5),
melee=dict(
att_dmg=12,
att_dmg_per_90_sec=0.5,
att_speed=1.250,
multiplicative_dmg_bonus_vs_turrets=1.5),
siege=dict(
att_dmg=39.5,
att_dmg_per_90_sec=1.5,
att_speed=1.000,
multiplicative_dmg_bonus_vs_turrets=1.5))
promote_buff_stats = dict(
caster=dict(
att_dmg=75,
att_speed_bonus=0.3),
melee=dict(
att_dmg=50,
att_speed_bonus=0.9),
siege=dict(
att_dmg=100,
# Since it would deal aoe dmg, we can assume it would hit 3 minions simultaneously.
multiplicative_dmg_bonus_vs_minions=3))
baron_buff_stats = dict(
caster=dict(
att_dmg=20),
melee=dict(
extra_percent_dmg_vs_minions=0.75,
),
siege=dict(
att_dmg=50,
att_speed_bonus=-0.5,
extra_percent_dmg_vs_turrets=1))
def final_att_dmg(minion_name, game_time, buffs_dcts):
"""
Returns total att_dmg after applying all bonuses.
:param minion_name: 'caster', 'melee' or 'cannon'
:param game_time: (int) Game time in minutes.
:param buffs_dcts: (list) List of buff dicts.
:return: (float)
"""
# Base attack damage
val = raw_minion_stats[minion_name]['att_dmg']
# Bonus by time
att_dmg_per_min = raw_minion_stats[minion_name]['att_dmg_per_90_sec'] / 1.5
val += att_dmg_per_min * game_time
# Bonus by buffs
for dct in buffs_dcts:
minion_buff_dct = dct[minion_name]
if 'att_dmg' in minion_buff_dct:
val += minion_buff_dct['att_dmg']
return val
def final_att_speed(minion_name, buffs_dcts):
# Base attack damage
val = raw_minion_stats[minion_name]['att_speed']
# Bonus by buffs
bonus_val = 0
for dct in buffs_dcts:
minion_buff_dct = dct[minion_name]
if 'att_speed_bonus' in minion_buff_dct:
bonus_val += minion_buff_dct['att_speed_bonus']
return val * (1 + bonus_val)
def unmitigated_dps(minion_name, game_time, buffs_dcts, versus):
"""
Calculates dmg per second of a minion with given buffs versus selected target,
without taking into account dmg resistances of target.
(Champion unmitigated_dps not available yet.)
DPS is irrelevant of combat duration.
:param versus: 'minions', or 'turrets'
:return:
"""
att_dmg = final_att_dmg(minion_name=minion_name, game_time=game_time, buffs_dcts=buffs_dcts)
att_speed = final_att_speed(minion_name=minion_name, buffs_dcts=buffs_dcts)
val = att_dmg * att_speed
extra_percent_dmg_keyword = 'extra_percent_dmg_vs_' + versus
for dct in buffs_dcts:
minion_buff_dct = dct[minion_name]
if extra_percent_dmg_keyword in minion_buff_dct:
val *= 1 + minion_buff_dct[extra_percent_dmg_keyword]
# Minions' final dmg gets a bonus vs turrets and a penalty vs champions.
multiplicative_bonus_keyword = ''
if versus == 'turrets':
multiplicative_bonus_keyword = 'multiplicative_dmg_bonus_vs_' + versus
elif versus == 'minions':
multiplicative_bonus_keyword = 'multiplicative_dmg_bonus_vs_' + versus
if multiplicative_bonus_keyword in raw_minion_stats[minion_name]:
val *= raw_minion_stats[minion_name][multiplicative_bonus_keyword]
return val
# =====================================================================================================================
# DISPLAY RESULTS
selected_game_time_in_minutes = 30
# All minions:
for _minion_name in sorted(raw_minion_stats):
msg = '\n' + '='*60
msg += '\nMinion: {}'.format(_minion_name)
for tar_name in ('turrets', 'minions'):
msg += '\n' + '-'*40
msg += '\nVS {}\n'.format(tar_name)
# promote
msg += '\npromote'
minion_dps = unmitigated_dps(minion_name=_minion_name,
game_time=selected_game_time_in_minutes,
buffs_dcts=[promote_buff_stats, ],
versus=tar_name)
msg += '\nDPS: {:.1f}'.format(minion_dps)
msg += '\n'
# Baron + promote
msg += '\nBaron + promote'
minion_dps = unmitigated_dps(minion_name=_minion_name,
game_time=selected_game_time_in_minutes,
buffs_dcts=[baron_buff_stats, promote_buff_stats],
versus=tar_name)
msg += '\nDPS: {:.1f}\n'.format(minion_dps)
print(msg)
Although i did check some of the results (and they seemed reasonable) I have not tested everything. In case you find a mistake, please let me know.