zapping is in fact in beam.cc and calls zappy about halfway through. (code In the spoiler at the bottom, it is rather irrelevant)
Siegurt's tr;dr is accurate: Mak's invocations are zap power-limited. See Zap Power Approx for more details below on Invo+2dInvo.
Edge's TLDR for this post is as follows:
Edge what do these numbers mean?Going from Invocations 0 to 10 increases the damage of minor destruction by ~57%.
Over 50% of the damage at all stages comes from stone arrow and breathe Acid, both of which scale well compared to the other three spells and are never or rarely resisted. This is significant at 0 invocations and they become even more dominant at higher invocations.
It doesn't really matter that shock is spellpower capped, shock represents <10% of Minor Destruction's Damage output. This is under an assumption that double zaps aren't a thing.
I never factored accuracy of spells into consideration.
The rest of this post is to give some clarification on how the power caps affect Minor Destruction.
The Shock Diminishing Returns
At Invocations 1-8, both minimum zap power and maximum zap power increase. Minimum = Invocations and Maximum = invocations x 3.
At Invocations 9-25, Minimum zap power is increased and maximum zap power gets rolled increasing frequency. Whenever invocations + 2d(invocations) - 2 >25, zap power is set to 25.
At Invocations >= 24, Zap always rolls max power.
Please note, roughly half of the gains average in zap power from 9 to 25 occur in the first 4 levels. That is the average zap power gain from invocations 9-13 is the same as the gain from 14-25. The difference in power gain going from 7 to 8 and going from 8 and 9 are vanishingly small (that is going from 8 to 9 is worth very slightly less than 7-8 but is barely noticable), and similarly the gain from 24-25 is also trivial, making going from invocations 24-25 to negligible practical purposes in the case of shock.
Throw Flame and Stone Arrow
At Invocations 1-16, both minimum zap power and maximum zap power increase.
At Invocations 17-50, minumum zap power increases and maximum zap power gets rolled with increasing frequency. Whenever invocations + 2d(invocations) - 2 >50, zap power is set to 50. Note half of the gains in average zap power from 17-50 would be clustered in levels 17-25.
At invocations 50+, Minor destruction will always roll max power on throw flame and stone arrow.
Breathe Acid and Pain
Breath Acid and Pain will increase minimum zap power and maximum zap power for all invocations 1-27.
From Power To DamageZap Damage Formulas.
This damage formula: return dice_def(numdice, adder + pow * mult_num / mult_denom); (code below in a spoiler)
Shocknew dicedef_calculator<1, 3, 1, 4>,
numdice=1, adder =3, pow = power, mult_num=1, and_mult denom=4
Thus, shock has a damage of 1d(3+pow*1/4) Max 1d9 @ Power 24
This is expected and matches the values on learnDB and the wiki.
Stone Arrow
new dicedef_calculator<3, 5, 1, 8>,
numdice=3, adder = 5, pow = power, mult_num=1, mult_denom=8
Thus, stone arrow has damage of 3d(5+pow*1/8) Max 3d11 @ power 48.
Throw Flame
new dicedef_calculator<2, 4, 1, 10>,
numdice=2, adder = 4, pow = power, mult_num=1, mult_denom=10
2d(4+pow*1/10). Max 2d9 @ power 50.
Breathe Acid
new dicedef_calculator<3, 4, 1, 3>,
numdice=3, adder = 4, pow = power, mult_num=1, mult_denom=3
3d(4+pow*1/3) Max 3d20 @ power 50, (note, pow here is pow/2 from Minor Destruction, for our purposes pow cannot be greater than 40.5 @ invocations 27, and caps at 3d17)
Pain
new dicedef_calculator<1, 4, 1, 5>,
numdice=1, adder = 4, pow = power, mult_num=1, mult_denom=5
1d(4+pow*1/5), max 1d(24) at power 100, (1d19 at invocations 27, also zap_pain is capped at power 100 while spell pain is capped at power 25)
Minor Destruction average damage at Various Invocation Levels
Invocations 0
Pow = 0
Shock 1d3 Ave 2
Pain 1d4 Ave 2.5
Throw Flame 2d4 Ave 5
Stone Arrow 3d5 Ave 9
Breathe Acid 3d3 Ave 6
Average Damage Minor Destrucion=
4.9Invocation 4
Ave Power 8, 4 for Breathe Acid
Shock 1d5 Ave 3
Pain 1d6.6 --? 1d6 Ave 3.5
Throw Flame 2d4.8 --> 2d4 Ave 5
Stone Arrow 3d6 Ave 10.5
Breathe Acid 3d4.33 --? 3d4 Ave 7.5
Average Damage Minor Destruction=
5.9 Invocation 10
Ave Power 20, 10 for Breathe Acid
Shock 1d8 Ave ~= 4.5 (Slightly less due to power cap)
Pain 1d8 Ave 4.5
Throw Flame 2d6 Ave 7
Stone Arrow 3d7.5 --? 3d7 Ave 12
Breathe Acid 3d6.33 --? 3d6 Ave 10.5
Average Damage Minor Destruction~=38.5/5=
7.7Edge what do these numbers mean?Going from Invocations 0 to 10 increases the damage of minor destruction by ~57%.
Over 50% of the damage at all stages comes from stone arrow and breathe Acid, both of which scale well compared to the other three spells and are never or rarely resisted. This is significant at 0 invocations and they become even more dominant at higher invocations.
It doesn't really matter that shock is spellpower capped, shock represents <10% of Minor Destruction's Damage output. This is under an assumption that double zaps aren't a thing.
I never factored accuracy of spells into consideration.
I don't know if 3d7.5 yields 3d7 or 3d8 or some combination of the two.
Junk MathAverage damage per point in invocations (I did these calculations before I did average damage at given invocation levels, which I could draw better conclusions from)
Max Damage
Shock gains 1/4 damage per zap power
Throw Flame gains 2/10=1/5 damage per zap power
Stone Arrow gains 3/8 damage per zap power
Pain gains 1/5 damage per zap power
Breath Acid gains 3/3=1 zap per power gains 3/6=1/2 zap per power/2
Max Damage per power= (1/4+1/5+3/8+1/5+1/2)/5. = .305
Average Damage per power= .1525
Average Power Per Level in invocations from 1-->8=2
Average damage increase per point in Invocations from 1-->8 .305 average damage
Average damage from 12-->13 ~= .28
Efficency loss = 8.2%
Other Stuff (Less relevant)
Spell Damage InfoCode for damage calculation and zap_info template, and zap data for Shock, Pain, Throw Flame, Stone Arrow, Breathe Acid, as well as Fireball and Iron Shot are under the spoiler. Something is going on with the damage for Iron Shot and Fireball and I don't understand what it is. However, it makes me question the above findings.
- Code:
class power_deducer
{
public:
virtual T operator()(int pow) const = 0;
virtual ~power_deducer() {}
};
typedef power_deducer<int> tohit_deducer;
template<int adder, int mult_num = 0, int mult_denom = 1>
class tohit_calculator : public tohit_deducer
{
public:
int operator()(int pow) const override
{
return adder + pow * mult_num / mult_denom;
}
};
typedef power_deducer<dice_def> dam_deducer;
template<int numdice, int adder, int mult_num, int mult_denom>
class dicedef_calculator : public dam_deducer
{
public:
dice_def operator()(int pow) const override
{
return dice_def(numdice, adder + pow * mult_num / mult_denom);
}
};
/*
struct zap_info
{
zap_type ztype;
const char* name;
int player_power_cap;
dam_deducer* player_damage;
tohit_deducer* player_tohit; // Enchantments have power modifier here
dam_deducer* monster_damage;
tohit_deducer* monster_tohit; // Enchantments have power modifier here
colour_t colour;
bool is_enchantment;
beam_type flavour;
dungeon_char_type glyph;
bool always_obvious;
bool can_beam;
bool is_explosion;
int hit_loudness;
}
*/
{
ZAP_SHOCK,
"zap",
25,
new dicedef_calculator<1, 3, 1, 4>,
new tohit_calculator<8, 1, 7>,
new dicedef_calculator<1, 8, 1, 20>,
new tohit_calculator<17, 1, 20>,
LIGHTCYAN,
false,
BEAM_ELECTRICITY, // beams & reflects
DCHAR_FIRED_ZAP,
true,
true,
false,
1 // XXX: maybe electricity should be louder?
},
{
ZAP_THROW_FLAME,
"puff of flame",
50,
new dicedef_calculator<2, 4, 1, 10>,
new tohit_calculator<8, 1, 10>,
new dicedef_calculator<3, 5, 1, 40>,
new tohit_calculator<25, 1, 40>,
RED,
false,
BEAM_FIRE,
DCHAR_FIRED_ZAP,
true,
false,
false,
2
},
{
ZAP_STONE_ARROW,
"stone arrow",
50,
new dicedef_calculator<3, 5, 1, 8>,
new tohit_calculator<8, 1, 10>,
new dicedef_calculator<3, 5, 1, 10>,
new tohit_calculator<14, 1, 35>,
LIGHTGREY,
false,
BEAM_MMISSILE,
DCHAR_FIRED_MISSILE,
true,
false,
false,
3
},
{
ZAP_BREATHE_ACID,
"glob of acid",
50,
new dicedef_calculator<3, 4, 1, 3>,
new tohit_calculator<7, 1, 6>,
nullptr,
nullptr,
YELLOW,
false,
BEAM_ACID,
DCHAR_FIRED_ZAP,
true,
false,
false,
6
},
{
ZAP_PAIN,
"",
100,
new dicedef_calculator<1, 4, 1, 5>,
new tohit_calculator<0, 7, 2>,
new dicedef_calculator<1, 7, 1, 20>,
new tohit_calculator<0, 1, 3>,
BLACK,
true,
BEAM_PAIN,
NUM_DCHAR_TYPES,
false,
false,
false,
1 // XXX: Should this be soundless?
},
{
ZAP_FIREBALL,
"fireball",
200,
new calcdice_calculator<3, 10, 1, 2>,
new tohit_calculator<40>,
new dicedef_calculator<3, 7, 1, 10>,
new tohit_calculator<40>,
RED,
false,
BEAM_FIRE,
DCHAR_FIRED_ZAP,
false,
false,
true,
0 // Noise comes from explosion
},
{
ZAP_IRON_SHOT,
"iron shot",
200,
new calcdice_calculator<9, 15, 3, 4>,
new tohit_calculator<7, 1, 15>,
new dicedef_calculator<3, 8, 1, 9>,
new tohit_calculator<20, 1, 25>,
LIGHTCYAN,
false,
BEAM_MMISSILE,
DCHAR_FIRED_MISSILE,
true,
false,
false,
6
},
Something unexpected is happening with other zaps:
Fireball
new calcdice_calculator<3, 10, 1, 2>,
numdice=3, adder = 10, pow = power, mult_num=1, mult_denom=2
3d(10+pow*1/2) --> up to 3d110 at max spellpower... wait this is wrong I expected it to be 3d(3.33+pow/6) lets check something else...Iron Shot
new calcdice_calculator<9, 15, 3, 4>,
numdice=9, adder = 15, pow = power, mult_num=3, mult_denom=4
Thus, Iron Shot has a damage of 9d(15+power*3/4) --> up do 9d165 at max spellpower...
This is unexpected, seems wrong, and does not match the wiki of 9d(1.66+power/12) capping at 9d19. At some point in time in iron shot, 15+power*3/4 gets divided by 9 to give 9d(1.55+power/12). A similar thing happens with fireball I'm clearly missing something here. This thing does not appear to be happening with stone arrow or throw flame. Zap Power Approx Zap Power Formula For Minor Destruction
Case A: Invocations+2d(Invocations+1)-2 is an accurate representation of zap power.
Case B: Invocations + 2d(Invocations) is a slightly better and easier to understand metric than Case C.
Case C: Invocations + 2d(Invocations+1) This is the least accurate, and leads you to believe diminishing returns begin at a invocation level 1 less than they actually are.
Given Zap power 5
Case A: 5+2d(6)-2 Will give a min of 5 + 0= 5 and a Max of 5+10=15: This is accurate.
Case B: 5+2d(5) Will give a min of 7 and a max of 15, This is 2 high for min but accurate for max
Case C: 5+2d(6) Will give a min of 5 7 and a max of 17, both of which are 2 off: This is 2 high in both min and max.
Case A is accurate, case B is conceptually the most straightforward and valuable and accurate enough.
code for zapping()
- Code:
spret_type zapping(zap_type ztype, int power, bolt &pbolt,
bool needs_tracer, const char* msg, bool fail)
{
dprf(DIAG_BEAM, "zapping: power=%d", power);
pbolt.thrower = KILL_YOU_MISSILE;
// Check whether tracer goes through friendlies.
// NOTE: Whenever zapping() is called with a randomised value for power
// (or effect), player_tracer should be called directly with the highest
// power possible respecting current skill, experience level, etc.
if (needs_tracer && !player_tracer(ztype, power, pbolt))
return SPRET_ABORT;
fail_check();
// Fill in the bolt structure.
zappy(ztype, power, false, pbolt);
if (msg)
mpr(msg);
if (ztype == ZAP_LIGHTNING_BOLT)
{
noisy(spell_effect_noise(SPELL_LIGHTNING_BOLT),
you.pos(), "You hear a mighty clap of thunder!");
pbolt.heard = true;
}
if (ztype == ZAP_DIG)
pbolt.aimed_at_spot = false;
pbolt.fire();
return SPRET_SUCCESS;
}