From 1c7e145a0a082b50c22ce53b6db7fccfc6ad9e31 Mon Sep 17 00:00:00 2001 From: haranp Date: Thu, 9 Oct 2008 13:59:30 +0000 Subject: Rewrite of beam.cc: put all beam data in one place. Might be buggy. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7201 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/acr.cc | 12 +- crawl-ref/source/beam.cc | 2073 +++++++++++++++++++----------------------- crawl-ref/source/decks.cc | 8 +- crawl-ref/source/effects.cc | 18 +- crawl-ref/source/enum.h | 4 +- crawl-ref/source/food.cc | 6 +- crawl-ref/source/invent.cc | 6 +- crawl-ref/source/it_use3.cc | 2 +- crawl-ref/source/item_use.cc | 26 +- crawl-ref/source/mstuff2.cc | 2 +- crawl-ref/source/newgame.cc | 3 +- crawl-ref/source/player.cc | 39 +- crawl-ref/source/skills.cc | 7 +- crawl-ref/source/spells1.cc | 6 +- crawl-ref/source/spells2.cc | 63 +- crawl-ref/source/spells3.cc | 50 +- crawl-ref/source/spl-cast.cc | 21 +- crawl-ref/source/traps.cc | 14 +- crawl-ref/source/tutorial.cc | 6 +- 19 files changed, 1084 insertions(+), 1282 deletions(-) (limited to 'crawl-ref/source') diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index 01dfd41993..a81e3b017d 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -2603,19 +2603,17 @@ static void _decrement_durations() you.duration[DUR_WEAPON_BRAND]--; else if (you.duration[DUR_WEAPON_BRAND] == 1) { - const int wpn = you.equip[EQ_WEAPON]; - const int temp_effect = get_weapon_brand( you.inv[wpn] ); + item_def& weapon = *you.weapon(); + const int temp_effect = get_weapon_brand(weapon); you.duration[DUR_WEAPON_BRAND] = 0; - - set_item_ego_type( you.inv[wpn], OBJ_WEAPONS, SPWPN_NORMAL ); - - std::string msg = you.inv[wpn].name(DESC_CAP_YOUR); + set_item_ego_type( weapon, OBJ_WEAPONS, SPWPN_NORMAL ); + std::string msg = weapon.name(DESC_CAP_YOUR); switch (temp_effect) { case SPWPN_VORPAL: - if (get_vorpal_type(you.inv[you.equip[EQ_WEAPON]]) == DVORP_SLICING) + if (get_vorpal_type(weapon) == DVORP_SLICING) msg += " seems blunter."; else msg += " feels lighter."; diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 0e2cbb4136..dfb88d11f7 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -219,11 +219,6 @@ bool zapping(zap_type ztype, int power, bolt &pbolt, bool needs_tracer, mprf(MSGCH_DIAGNOSTICS, "zapping: power=%d", power ); #endif - // GDL: note that rangeMax is set to 0, which means that max range is - // equal to range. This is OK, since rangeMax really only matters for - // stuff monsters throw/zap. - - // All of the following settings might be changed by _zappy(). _beam_set_default_values(pbolt, power); // For player bolts, check whether tracer goes through friendlies. @@ -244,11 +239,9 @@ bool zapping(zap_type ztype, int power, bolt &pbolt, bool needs_tracer, mpr(msg.c_str()); if (ztype == ZAP_LIGHTNING) - { - // XXX: Needs to check silenced at other location, too. {dlb} noisy(25, you.pos(), "You hear a mighty clap of thunder!"); - } - else if (ztype == ZAP_DIGGING) + + if (ztype == ZAP_DIGGING) pbolt.aimed_at_spot = false; fire_beam(pbolt); @@ -256,310 +249,6 @@ bool zapping(zap_type ztype, int power, bolt &pbolt, bool needs_tracer, return (true); } -// pbolt needs to be initialized for tracing: with the the maximum range, -// and the flavour to allow for completely resistant monsters. -static void _get_max_range( zap_type z_type, int power, bolt &pbolt ) -{ - // sorted by range - switch (z_type) - { - case ZAP_SMALL_SANDBLAST: - pbolt.flavour = BEAM_FRAG; - break; - - case ZAP_SANDBLAST: - pbolt.flavour = BEAM_FRAG; - break; - - case ZAP_FLAME_TONGUE: - if (power > 25) - power = 25; - - pbolt.flavour = BEAM_FIRE; - break; - - case ZAP_CLEANSING_FLAME: - pbolt.name = "golden flame"; - pbolt.flavour = BEAM_HOLY; - pbolt.is_explosion = true; - break; - - case ZAP_MAGMA: - pbolt.flavour = BEAM_LAVA; - pbolt.is_beam = true; - break; - - case ZAP_IRON_BOLT: - pbolt.flavour = BEAM_MMISSILE; // unresistable - break; - - case ZAP_CRYSTAL_SPEAR: - pbolt.flavour = BEAM_MMISSILE; // unresistable - break; - - case ZAP_SPIT_POISON: - if (power > 50) - power = 50; - - pbolt.flavour = BEAM_POISON; - break; - - case ZAP_BREATHE_FIRE: - if (power > 50) - power = 50; - - pbolt.flavour = BEAM_FIRE; - pbolt.is_beam = true; - break; - - case ZAP_BREATHE_FROST: - if (power > 50) - power = 50; - - pbolt.flavour = BEAM_COLD; - pbolt.is_beam = true; - break; - - case ZAP_BREATHE_ACID: - if (power > 50) - power = 50; - - pbolt.flavour = BEAM_ACID; - pbolt.is_beam = true; - break; - - case ZAP_BREATHE_POISON: // leaves clouds of gas - if (power > 50) - power = 50; - - pbolt.flavour = BEAM_POISON; - pbolt.is_beam = true; - break; - - case ZAP_BREATHE_POWER: - if (power > 50) - power = 50; - - pbolt.flavour = BEAM_MMISSILE; // unresistable - pbolt.is_beam = true; - break; - - case ZAP_BREATHE_STEAM: - pbolt.flavour = BEAM_STEAM; - pbolt.is_beam = true; - break; - - case ZAP_STRIKING: - case ZAP_MAGIC_DARTS: - case ZAP_STONE_ARROW: - case ZAP_MYSTIC_BLAST: - pbolt.flavour = BEAM_MMISSILE; // unresistable - break; - - case ZAP_STING: - case ZAP_POISON_ARROW: - pbolt.flavour = BEAM_POISON; - break; - - case ZAP_FLAME: - case ZAP_STICKY_FLAME: - pbolt.flavour = BEAM_FIRE; - break; - - case ZAP_FROST: - pbolt.flavour = BEAM_COLD; - break; - - case ZAP_ICE_BOLT: - pbolt.flavour = BEAM_ICE; // half resistable - break; - - case ZAP_ELECTRICITY: - pbolt.flavour = BEAM_ELECTRICITY; // beams & reflects - pbolt.is_beam = true; - break; - - case ZAP_DISRUPTION: - case ZAP_DISINTEGRATION: - pbolt.name = "0"; - pbolt.flavour = BEAM_DISINTEGRATION; - break; - - case ZAP_PAIN: - pbolt.name = "0"; - pbolt.flavour = BEAM_PAIN; - break; - - case ZAP_DISPEL_UNDEAD: - pbolt.name = "0"; - pbolt.flavour = BEAM_DISPEL_UNDEAD; - break; - - case ZAP_FIRE: - pbolt.flavour = BEAM_FIRE; - pbolt.is_beam = true; - break; - - case ZAP_BONE_SHARDS: - pbolt.flavour = BEAM_MAGIC; // unresisted - pbolt.is_beam = true; - break; - - case ZAP_COLD: - pbolt.flavour = BEAM_COLD; - pbolt.is_beam = true; - break; - - case ZAP_NEGATIVE_ENERGY: - pbolt.flavour = BEAM_NEG; // drains levels - pbolt.is_beam = true; - break; - - case ZAP_BEAM_OF_ENERGY: // bolt of innacuracy - pbolt.flavour = BEAM_ENERGY; // unresisted - pbolt.is_beam = true; - break; - - case ZAP_VENOM_BOLT: - pbolt.flavour = BEAM_POISON; - pbolt.is_beam = true; - break; - - case ZAP_LIGHTNING: - pbolt.flavour = BEAM_ELECTRICITY; // beams & reflects - pbolt.is_beam = true; - break; - - // enchantments - case ZAP_ENSLAVEMENT: - pbolt.name = "0"; - pbolt.flavour = BEAM_CHARM; - break; - - case ZAP_BANISHMENT: - pbolt.name = "0"; - pbolt.flavour = BEAM_BANISH; - break; - - case ZAP_DEGENERATION: - pbolt.name = "0"; - pbolt.flavour = BEAM_DEGENERATE; - break; - - case ZAP_ENSLAVE_UNDEAD: - pbolt.name = "0"; - pbolt.flavour = BEAM_ENSLAVE_UNDEAD; - break; - - case ZAP_CONTROL_DEMON: - pbolt.name = "0"; - pbolt.flavour = BEAM_ENSLAVE_DEMON; - break; - - case ZAP_SLEEP: - pbolt.name = "0"; - pbolt.flavour = BEAM_SLEEP; - break; - - case ZAP_BACKLIGHT: - pbolt.name = "0"; - pbolt.flavour = BEAM_BACKLIGHT; - break; - - case ZAP_SLOWING: - pbolt.name = "0"; - pbolt.flavour = BEAM_SLOW; - break; - - case ZAP_HASTING: - pbolt.name = "0"; - pbolt.flavour = BEAM_HASTE; - break; - - case ZAP_PARALYSIS: - pbolt.name = "0"; - pbolt.flavour = BEAM_PARALYSIS; - break; - - case ZAP_PETRIFY: - pbolt.name = "0"; - pbolt.flavour = BEAM_PETRIFY; - break; - - case ZAP_CONFUSION: - pbolt.name = "0"; - pbolt.flavour = BEAM_CONFUSION; - break; - - case ZAP_INVISIBILITY: - pbolt.name = "0"; - pbolt.flavour = BEAM_INVISIBILITY; - break; - - case ZAP_HEALING: - pbolt.name = "0"; - pbolt.flavour = BEAM_HEALING; - break; - - case ZAP_TELEPORTATION: - pbolt.name = "0"; - pbolt.flavour = BEAM_TELEPORT; - break; - - case ZAP_POLYMORPH_OTHER: - pbolt.name = "0"; - pbolt.flavour = BEAM_POLYMORPH; - break; - - case ZAP_AGONY: - pbolt.name = "0agony"; - pbolt.flavour = BEAM_PAIN; - break; - - case ZAP_DIGGING: - pbolt.name = "0"; - pbolt.flavour = BEAM_DIGGING; - pbolt.is_beam = true; - break; - - // explosions - case ZAP_FIREBALL: - pbolt.name = "fireball"; - pbolt.flavour = BEAM_FIRE; // fire - pbolt.is_explosion = true; - break; - - case ZAP_ICE_STORM: - pbolt.name = "great blast of cold"; - pbolt.ench_power = power; // used for radius - pbolt.flavour = BEAM_ICE; // half resisted - pbolt.is_explosion = true; - break; - - case ZAP_ORB_OF_FRAGMENTATION: // cap 150 - pbolt.name = "metal orb"; - pbolt.flavour = BEAM_FRAG; // extra AC resist - pbolt.is_explosion = true; - break; - - case ZAP_HELLFIRE: - pbolt.flavour = BEAM_HELLFIRE; - pbolt.is_explosion = true; - break; - - case ZAP_ORB_OF_ELECTRICITY: // cap 150 - pbolt.name = "orb of electricity"; - pbolt.flavour = BEAM_ELECTRICITY; - pbolt.is_explosion = true; - break; - - case ZAP_DEBUGGING_RAY: - default: // buggy beam - pbolt.flavour = BEAM_MMISSILE; // unresistable - break; - } -} - // Returns true if the path is considered "safe", and false if there are // monsters in the way the player doesn't want to hit. // NOTE: Doesn't check for the player being hit by a rebounding lightning bolt. @@ -572,7 +261,6 @@ bool player_tracer( zap_type ztype, int power, bolt &pbolt, int range) _beam_set_default_values(pbolt, power); pbolt.name = "unimportant"; - _get_max_range(ztype, power, pbolt); pbolt.is_tracer = true; pbolt.source = you.pos(); @@ -633,856 +321,1030 @@ dice_def calc_dice( int num_dice, int max_damage ) return (ret); } -// Need to see zapping() for default values not set within this function {dlb} -static void _zappy( zap_type z_type, int power, bolt &pbolt ) +template +struct power_deducer { - int temp_rand = 0; // probability determination {dlb} - - // Note: The incoming power is not linear in the case of spellcasting. - // The power curve currently allows for the character to reasonably - // get up to a power level of about a 100, but more than that will - // be very hard (and the maximum is 200). The low level power caps - // provide the useful feature in that they allow for low level spells - // to have quick advancement, but don't cause them to obsolete the - // higher level spells. -- bwr - // - // I've added some example characters below to show how little - // people should be concerned about the power caps. - // - // The example characters are simplified to three stats: - // - // - Intelligence: This magnifies power, it's very useful. - // - // - Skills: This represents the character having Spellcasting - // and the average of the component skills at this level. - // Although, Spellcasting probably isn't quite as high as - // other spell skills for a lot of characters, note that it - // contributes much less to the total power (about 20%). - // - // - Enhancers: These are equipment that the player can use to - // apply additional magnifiers (x1.5) to power. There are - // also inhibitors that reduce power (/2.0), but we're not - // concerned about those here. Anyways, the character can - // currently have up to 3 levels (for x1.5, x2.25, x3.375). - // The lists below should help to point out the difficulty - // and cost of getting more than one level of enhancement. - // - // Here's a list of current magnifiers: - // - // - rings of fire/cold - // - staff of fire/cold/air/earth/poison/death/conjure/enchant/summon - // - staff of Olgreb (poison) - // - robe of the Archmagi (necro, conjure, enchant, summon) - // - Mummy intrinsic (+1 necromancy at level 13, +2 at level 26) - // - Necromutation (+1 to necromancy -- note: undead can't use this) - // - Ring of Fire (+1 to fire) - // - // The maximum enhancement, by school (but capped at 3): - // - // - Necromancy: 4 (Mummies), 3 (others) - // - Fire: 4 - // - Cold: 3 - // - Conjuration: 2 - // - Enchantment: 2 - // - Summoning: 2 - // - Air: 1 - // - Earth: 1 - // - Poison: 1 - // - Translocations, Transmigrations, Divinations intentionally 0 - - switch (z_type) - { - // level 1 - // - // This cap is to keep these easy and very cheap spells from - // becoming too powerful. - // - // Example characters with about 25 power: - // - // - int 5, skills 20, 0 enhancers - // - int 5, skills 14, 1 enhancer - // - int 10, skills 10, 0 enhancers - // - int 10, skills 7, 1 enhancers - // - int 15, skills 7, 0 enhancers - // - int 20, skills 6, 0 enhancers - case ZAP_STRIKING: - case ZAP_MAGIC_DARTS: - case ZAP_STING: - case ZAP_ELECTRICITY: - case ZAP_FLAME_TONGUE: - case ZAP_SMALL_SANDBLAST: - case ZAP_DISRUPTION: // ench_power boosted below - case ZAP_PAIN: // ench_power boosted below - if (power > 25) - power = 25; - break; - - // level 2/3 - // - // The following examples should make it clear that in the - // early game this cap is only limiting to serious spellcasters - // (they could easily reach the 20-10-0 example). - // - // Example characters with about 50 power: - // - // - int 10, skills 20, 0 enhancers - // - int 10, skills 14, 1 enhancer - // - int 15, skills 14, 0 enhancers - // - int 15, skills 10, 1 enhancer - // - int 20, skills 10, 0 enhancers - // - int 20, skills 7, 1 enhancer - // - int 25, skills 8, 0 enhancers - case ZAP_SANDBLAST: - case ZAP_FLAME: // also ability (pow = lev * 2) - case ZAP_FROST: // also ability (pow = lev * 2) - case ZAP_STONE_ARROW: - if (power > 50) - power = 50; - break; - - // Here are some examples that show that its fairly safe to assume - // that a high level character can easily have 75 power. - // - // Example characters with about 75 power: - // - // - int 10, skills 27, 1 enhancer - // - int 15, skills 27, 0 enhancers - // - int 15, skills 16, 1 enhancer - // - int 20, skills 20, 0 enhancers - // - int 20, skills 14, 1 enhancer - // - int 25, skills 16, 0 enhancers - - // level 4 - // - // The following examples should make it clear that this is the - // effective maximum power. Its not easy to get to 100 power, - // but 20-20-1 or 25-16-1 is certainly attainable by a high level - // spellcaster. As you can see from the examples at 150 and 200, - // getting much power beyond this is very difficult. - // - // Level 3 and 4 spells cannot be overpowered. - // - // Example characters with about 100 power: - // - // - int 10, skills 27, 2 enhancers - // - int 15, skills 27, 1 enhancer - // - int 20, skills 20, 1 enhancer - // - int 25, skills 24, 0 enhancers - // - int 25, skills 16, 1 enhancer - case ZAP_MYSTIC_BLAST: - case ZAP_STICKY_FLAME: - case ZAP_ICE_BOLT: - case ZAP_DISPEL_UNDEAD: // ench_power raised below - if (power > 100) - power = 100; - break; - - // levels 5-7 - // - // These spells used to be capped, but its very hard to raise - // power over 100, and these examples should show that. - // Only the twinkiest of characters are expected to get to 150. - // - // Example characters with about 150 power: - // - // - int 15, skills 27, 3 enhancers (actually, only 146) - // - int 20, skills 27, 2 enhancers (actually, only 137) - // - int 20, skills 21, 3 enhancers - // - int 25, skills 26, 2 enhancers - // - int 30, skills 21, 2 enhancers - // - int 40, skills 24, 1 enhancer - // - int 70, skills 20, 0 enhancers - case ZAP_FIRE: - case ZAP_COLD: - case ZAP_VENOM_BOLT: - case ZAP_MAGMA: - case ZAP_AGONY: - case ZAP_LIGHTNING: // also invoc * 6 or lev * 2 (abils) - case ZAP_NEGATIVE_ENERGY: // also ability (pow = lev * 6) - case ZAP_IRON_BOLT: - case ZAP_DISINTEGRATION: - case ZAP_FIREBALL: - case ZAP_ORB_OF_ELECTRICITY: - case ZAP_ORB_OF_FRAGMENTATION: - case ZAP_POISON_ARROW: - // if (power > 150) - // power = 150; - break; + virtual T operator()(int pow) const = 0; +}; - // levels 8-9 - // - // These spells are capped at 200 (which is the cap in calc_spell_power). - // As an example of how little of a cap that is, consider the fact - // that a 70-27-3 character has an uncapped power of 251. Characters - // are never expected to get to this cap. - // - // Example characters with about 200 power: - // - // - int 30, skills 27, 3 enhancers (actually, only 190) - // - int 40, skills 27, 2 enhancers (actually, only 181) - // - int 40, skills 23, 3 enhancers - // - int 70, skills 27, 0 enhancers (actually, only 164) - // - int 70, skills 27, 1 enhancers (actually, only 194) - // - int 70, skills 20, 2 enhancers - // - int 70, skills 13, 3 enhancers - case ZAP_CRYSTAL_SPEAR: - case ZAP_HELLFIRE: - case ZAP_ICE_STORM: - case ZAP_CLEANSING_FLAME: - // if (power > 200) - // power = 200; - break; +typedef power_deducer tohit_deducer; - // unlimited power (needs a good reason) - case ZAP_BONE_SHARDS: // incoming power is modified for mass - case ZAP_BEAM_OF_ENERGY: // inaccuracy (only on staff, hardly hits) - break; +template +struct tohit_calculator : public tohit_deducer +{ + int operator()(int pow) const + { + return adder + (pow * mult_num) / mult_denom; + } +}; - // natural/mutant breath/spit powers (power ~= characer level) - case ZAP_SPIT_POISON: // lev + mut * 5 - case ZAP_BREATHE_FIRE: // lev + mut * 4 + 12 (if dragonform) - case ZAP_BREATHE_FROST: // lev - case ZAP_BREATHE_ACID: // lev (or invoc * 3 from minor destr) - case ZAP_BREATHE_POISON: // lev - case ZAP_BREATHE_POWER: // lev - case ZAP_BREATHE_STEAM: // lev - if (power > 50) - power = 50; - break; +typedef power_deducer dam_deducer; - // enchantments and other resistable effects - case ZAP_SLOWING: - case ZAP_HASTING: - case ZAP_PARALYSIS: - case ZAP_PETRIFY: - case ZAP_BACKLIGHT: - case ZAP_SLEEP: - case ZAP_CONFUSION: - case ZAP_INVISIBILITY: - case ZAP_ENSLAVEMENT: - case ZAP_TELEPORTATION: - case ZAP_DIGGING: - case ZAP_POLYMORPH_OTHER: - case ZAP_DEGENERATION: - case ZAP_BANISHMENT: - // This is the only power that matters. We magnify it apparently - // to get values that work better with magic resistance checks... - // those checks will scale down this value and max it out at 120. - pbolt.ench_power *= 3; - pbolt.ench_power /= 2; - break; +template +struct dicedef_calculator : public dam_deducer +{ + dice_def operator()(int pow) const + { + return dice_def(numdice, adder + (pow * mult_num) / mult_denom); + } +}; - // anything else we cap to 100 - default: - if (power > 100) - power = 100; - break; +template +struct calcdice_calculator : public dam_deducer +{ + dice_def operator()(int pow) const + { + return calc_dice(numdice, adder + (pow * mult_num) / mult_denom); } +}; - // Note: I'm only displaying the top damage and such here, that's - // because it's really not been known before (since the above caps - // didn't exist), so they were all pretty much unlimited before. - // Also note, that the high end damage occurs at the cap, only - // players that are that powerful can get that damage... and - // although these numbers might seem small, you should remember - // that Dragons in this game are 60-90 hp monsters, and very - // few monsters have more than 100 hp (and that 1d5 damage is - // still capable of taking a good sized chunk (and possibly killing) - // any monster you're likely to meet in the first three levels). -- bwr - - // Note: damage > 100 signals that "random2(damage - 100)" will be - // applied three times, which not only ups the damage but gives - // a more normal distribution. - switch (z_type) - { - case ZAP_STRIKING: // cap 25 - pbolt.name = "force bolt"; - pbolt.colour = BLACK; - pbolt.damage = dice_def( 1, 5 ); // dam: 5 - pbolt.hit = 8 + power / 10; // 25: 10 - pbolt.type = dchar_glyph(DCHAR_SPACE); - pbolt.flavour = BEAM_MMISSILE; // unresistable - pbolt.obvious_effect = true; - break; +struct zap_info +{ + zap_type ztype; + const char* name; // NULL means handled specially + int power_cap; + dam_deducer* damage; + tohit_deducer* tohit; // Enchantments have power modifier here + int colour; + bool is_enchantment; + beam_type flavour; + dungeon_char_type glyph; + bool always_obvious; + bool can_beam; + bool is_explosion; +}; + +const zap_info zap_data[] = { - case ZAP_MAGIC_DARTS: // cap 25 - pbolt.name = "magic dart"; - pbolt.colour = LIGHTMAGENTA; - pbolt.damage = dice_def( 1, 3 + power / 5 ); // 25: 1d8 - pbolt.hit = AUTOMATIC_HIT; // hits always - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_MMISSILE; // unresistable - pbolt.obvious_effect = true; - break; + { + ZAP_FLAME, + "puff of flame", + 50, + new dicedef_calculator<2, 4, 1, 10>, + new tohit_calculator<8, 1, 10>, + RED, + false, + BEAM_FIRE, + DCHAR_FIRED_ZAP, + true, + false, + false + }, - case ZAP_STING: // cap 25 - pbolt.name = "sting"; - pbolt.colour = GREEN; - pbolt.damage = dice_def( 1, 3 + power / 5 ); // 25: 1d8 - pbolt.hit = 8 + power / 5; // 25: 13 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_POISON; // extra damage - pbolt.obvious_effect = true; - break; + { + ZAP_FROST, + "puff of frost", + 50, + new dicedef_calculator<2, 4, 1, 10>, + new tohit_calculator<8, 1, 10>, + WHITE, + false, + BEAM_COLD, + DCHAR_FIRED_ZAP, + true, + false, + false + }, - case ZAP_ELECTRICITY: // cap 20 - pbolt.name = "zap"; - pbolt.colour = LIGHTCYAN; - pbolt.damage = dice_def( 1, 3 + random2(power) / 2 );// 25: 1d11 - pbolt.hit = 8 + power / 7; // 25: 11 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_ELECTRICITY; // beams & reflects - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; + { + ZAP_SLOWING, + "0", + 100, + NULL, + NULL, + BLACK, + true, + BEAM_SLOW, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_DISRUPTION: // cap 25 - pbolt.name = "0"; - pbolt.flavour = BEAM_DISINTEGRATION; - pbolt.damage = dice_def( 1, 4 + power / 5 ); // 25: 1d9 - pbolt.ench_power *= 3; - break; + { + ZAP_HASTING, + "0", + 100, + NULL, + NULL, + BLACK, + true, + BEAM_HASTE, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_PAIN: // cap 25 - pbolt.name = "0"; - pbolt.flavour = BEAM_PAIN; - pbolt.damage = dice_def( 1, 4 + power / 5 ); // 25: 1d9 - pbolt.ench_power *= 7; - pbolt.ench_power /= 2; - break; + { + ZAP_MAGIC_DARTS, + "magic dart", + 25, + new dicedef_calculator<1, 3, 1, 5>, + new tohit_calculator, + LIGHTMAGENTA, + false, + BEAM_MMISSILE, + DCHAR_FIRED_ZAP, + true, + false, + false + }, + + { + ZAP_HEALING, + "0", + 100, + new dicedef_calculator<1, 7, 1, 3>, + NULL, + BLACK, + true, + BEAM_HEALING, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_FLAME_TONGUE: // cap 25 - pbolt.name = "flame"; - pbolt.colour = RED; - pbolt.damage = dice_def( 1, 8 + power / 4 ); // 25: 1d14 - pbolt.hit = 7 + power / 6; // 25: 11 - pbolt.type = dchar_glyph(DCHAR_FIRED_BOLT); - pbolt.flavour = BEAM_FIRE; - pbolt.obvious_effect = true; - break; + { + ZAP_PARALYSIS, + "0", + 100, + NULL, + NULL, + BLACK, + true, + BEAM_PARALYSIS, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_SMALL_SANDBLAST: // cap 25 - pbolt.name = "blast of "; + { + ZAP_FIRE, + "bolt of fire", + 200, + new calcdice_calculator<6, 18, 2, 3>, + new tohit_calculator<10, 1, 25>, + RED, + false, + BEAM_FIRE, + DCHAR_FIRED_ZAP, + true, + true, + false + }, + + { + ZAP_COLD, + "bolt of cold", + 200, + new calcdice_calculator<6, 18, 2, 3>, + new tohit_calculator<10, 1, 25>, + WHITE, + false, + BEAM_COLD, + DCHAR_FIRED_ZAP, + true, + true, + false + }, + + { + ZAP_CONFUSION, + "0", + 100, + NULL, + NULL, + BLACK, + true, + BEAM_CONFUSION, + DCHAR_SPACE, + false, + false, + false + }, - temp_rand = random2(4); - pbolt.name += (temp_rand == 0) ? "dust" : - (temp_rand == 1) ? "dirt" : - (temp_rand == 2) ? "grit" : "sand"; + { + ZAP_INVISIBILITY, + "0", + 100, + NULL, + NULL, + BLACK, + true, + BEAM_INVISIBILITY, + DCHAR_SPACE, + false, + false, + false + }, - pbolt.colour = BROWN; - pbolt.damage = dice_def( 1, 8 + power / 4 ); // 25: 1d14 - pbolt.hit = 8 + power / 5; // 25: 13 - pbolt.type = dchar_glyph(DCHAR_FIRED_BOLT); - pbolt.flavour = BEAM_FRAG; // extra AC resist - pbolt.obvious_effect = true; - break; + { + ZAP_DIGGING, + "0", + 100, + NULL, + NULL, + BLACK, + true, + BEAM_DIGGING, + DCHAR_SPACE, + false, + true, + false + }, - case ZAP_SANDBLAST: // cap 50 - pbolt.name = coinflip() ? "blast of rock" : "rocky blast"; - pbolt.colour = BROWN; - pbolt.damage = dice_def( 2, 4 + power / 3 ); // 25: 2d12 - pbolt.hit = 13 + power / 10; // 25: 15 - pbolt.type = dchar_glyph(DCHAR_FIRED_BOLT); - pbolt.flavour = BEAM_FRAG; // extra AC resist - pbolt.obvious_effect = true; - break; + { + ZAP_FIREBALL, + "fireball", + 200, + new calcdice_calculator<3, 10, 1, 2>, + new tohit_calculator<40>, + RED, + false, + BEAM_FIRE, + DCHAR_FIRED_ZAP, + false, + false, + true + }, - case ZAP_BONE_SHARDS: - pbolt.name = "spray of bone shards"; - pbolt.colour = LIGHTGREY; + { + ZAP_TELEPORTATION, + "0", + 100, + NULL, + NULL, + BLACK, + true, + BEAM_TELEPORT, + DCHAR_SPACE, + false, + false, + false + }, - // Incoming power is highly dependant on mass (see spells3.cc). - // Basic function is power * 15 + mass... with the largest - // available mass (3000) we get a power of 4500 at a power - // level of 100 (for 3d20). - pbolt.damage = dice_def( 3, 2 + (power / 250) ); - pbolt.hit = 8 + (power / 100); // max hit: 53 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_MAGIC; // unresisted - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; + { + ZAP_LIGHTNING, + "bolt of lightning", + 200, + new calcdice_calculator<1, 10, 3, 5>, + new tohit_calculator<7, 1, 40>, + LIGHTCYAN, + false, + BEAM_ELECTRICITY, + DCHAR_FIRED_ZAP, + true, + true, + false + }, - case ZAP_FLAME: // cap 50 - pbolt.name = "puff of flame"; - pbolt.colour = RED; - pbolt.damage = dice_def( 2, 4 + power / 10 );// 25: 2d6 50: 2d9 - pbolt.hit = 8 + power / 10; // 25: 10 50: 13 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_FIRE; - pbolt.obvious_effect = true; - break; + { + ZAP_POLYMORPH_OTHER, + "0", + 100, + NULL, + NULL, + BLACK, + true, + BEAM_POLYMORPH, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_FROST: // cap 50 - pbolt.name = "puff of frost"; - pbolt.colour = WHITE; - pbolt.damage = dice_def( 2, 4 + power / 10 );// 25: 2d6 50: 2d9 - pbolt.hit = 8 + power / 10; // 25: 10 50: 13 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_COLD; - pbolt.obvious_effect = true; - break; + { + ZAP_VENOM_BOLT, + "bolt of poison", + 200, + new calcdice_calculator<4, 15, 1, 2>, + new tohit_calculator<8, 1, 20>, + LIGHTGREEN, + false, + BEAM_POISON, + DCHAR_FIRED_ZAP, + true, + true, + false + }, + + { + ZAP_NEGATIVE_ENERGY, + "bolt of negative energy", + 200, + new calcdice_calculator<4, 15, 3, 5>, + new tohit_calculator<8, 1, 20>, + DARKGREY, + false, + BEAM_NEG, + DCHAR_FIRED_ZAP, + true, + true, + false + }, - case ZAP_STONE_ARROW: // cap 100 - pbolt.name = "stone arrow"; - pbolt.colour = LIGHTGREY; - pbolt.damage = dice_def( 2, 5 + power / 7 );// 25: 2d8 50: 2d12 - pbolt.hit = 8 + power / 10; // 25: 10 50: 13 - pbolt.type = dchar_glyph(DCHAR_FIRED_MISSILE); - pbolt.flavour = BEAM_MMISSILE; // irresistible - pbolt.obvious_effect = true; - break; + { + ZAP_CRYSTAL_SPEAR, + "crystal spear", + 200, + new calcdice_calculator<10, 23, 1, 1>, + new tohit_calculator<10, 1, 15>, + WHITE, + false, + BEAM_MMISSILE, + DCHAR_FIRED_MISSILE, + true, + false, + false + }, - case ZAP_STICKY_FLAME: // cap 100 - pbolt.name = "sticky flame"; // extra damage - pbolt.colour = RED; - // 50: 2d7 100: 2d11 - pbolt.damage = dice_def( 2, 3 + power / 12 ); - // 50: 16 100: 21 - pbolt.hit = 11 + power / 10; - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_FIRE; - pbolt.obvious_effect = true; - break; + { + ZAP_BEAM_OF_ENERGY, + "narrow beam of energy", + 1000, + new calcdice_calculator<12, 40, 3, 2>, + new tohit_calculator<1>, + YELLOW, + false, + BEAM_ENERGY, + DCHAR_FIRED_ZAP, + true, + true, + false + }, - case ZAP_MYSTIC_BLAST: // cap 100 - pbolt.name = "orb of energy"; - pbolt.colour = LIGHTMAGENTA; - pbolt.damage = calc_dice( 2, 15 + (power * 2) / 5 ); - pbolt.hit = 10 + power / 7; // 50: 17 100: 24 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_MMISSILE; // unresistable - pbolt.obvious_effect = true; - break; + { + ZAP_MYSTIC_BLAST, + "orb of energy", + 100, + new calcdice_calculator<2, 15, 2, 5>, + new tohit_calculator<10, 1, 7>, + LIGHTMAGENTA, + false, + BEAM_MMISSILE, + DCHAR_FIRED_ZAP, + true, + false, + false + }, - case ZAP_ICE_BOLT: // cap 100 - pbolt.name = "bolt of ice"; - pbolt.colour = WHITE; - pbolt.damage = calc_dice( 3, 10 + power / 2 ); - pbolt.hit = 9 + power / 12; // 50: 13 100: 17 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_ICE; // half resistable - break; + { + ZAP_ENSLAVEMENT, + "0", + 100, + NULL, + NULL, + BLACK, + true, + BEAM_CHARM, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_DISPEL_UNDEAD: // cap 100 - pbolt.name = "0"; - pbolt.flavour = BEAM_DISPEL_UNDEAD; - pbolt.damage = calc_dice( 3, 20 + (power * 3) / 4 ); - pbolt.ench_power *= 3; - pbolt.ench_power /= 2; - break; + { + ZAP_PAIN, + "0", + 100, + new dicedef_calculator<1, 4, 1,5>, + new tohit_calculator<0, 7, 2>, + BLACK, + true, + BEAM_PAIN, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_MAGMA: // cap 150 - pbolt.name = "bolt of magma"; - pbolt.colour = RED; - pbolt.damage = calc_dice( 4, 10 + (power * 3) / 5 ); - pbolt.hit = 8 + power / 25; // 50: 10 100: 14 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_LAVA; - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; + { + ZAP_STICKY_FLAME, + "sticky flame", + 100, + new dicedef_calculator<2, 3, 1, 12>, + new tohit_calculator<11, 1, 10>, + RED, + false, + BEAM_FIRE, + DCHAR_FIRED_ZAP, + true, + false, + false + }, - case ZAP_FIRE: // cap 150 - pbolt.name = "bolt of fire"; - pbolt.colour = RED; - pbolt.damage = calc_dice( 6, 18 + power * 2 / 3 ); - pbolt.hit = 10 + power / 25; // 50: 12 100: 14 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_FIRE; - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; + { + ZAP_DISPEL_UNDEAD, + "0", + 100, + new calcdice_calculator<3, 20, 3, 4>, + new tohit_calculator<0, 3, 2>, + BLACK, + true, + BEAM_DISPEL_UNDEAD, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_COLD: // cap 150 - pbolt.name = "bolt of cold"; - pbolt.colour = WHITE; - pbolt.damage = calc_dice( 6, 18 + power * 2 / 3 ); - pbolt.hit = 10 + power / 25; // 50: 12 100: 14 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_COLD; - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; - case ZAP_VENOM_BOLT: // cap 150 - pbolt.name = "bolt of poison"; - pbolt.colour = LIGHTGREEN; - pbolt.damage = calc_dice( 4, 15 + power / 2 ); - pbolt.hit = 8 + power / 20; // 50: 10 100: 13 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_POISON; // extra damage - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; + { + ZAP_CLEANSING_FLAME, + "golden flame", + 200, + new calcdice_calculator<2, 20, 2, 3>, + new tohit_calculator<150>, + YELLOW, + false, + BEAM_HOLY, + DCHAR_FIRED_ZAP, + true, + true, + false + }, - case ZAP_NEGATIVE_ENERGY: // cap 150 - // These always auto-identify, so no generic name. - pbolt.name = "bolt of negative energy"; - pbolt.colour = DARKGREY; - pbolt.damage = calc_dice( 4, 15 + (power * 3) / 5 ); - pbolt.hit = 8 + power / 20; // 50: 10 100: 13 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_NEG; // drains levels - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; - case ZAP_IRON_BOLT: // cap 150 - pbolt.name = "iron bolt"; - pbolt.colour = LIGHTCYAN; - pbolt.damage = calc_dice( 9, 15 + (power * 3) / 4 ); - pbolt.hit = 7 + power / 15; // 50: 10 100: 13 - pbolt.type = dchar_glyph(DCHAR_FIRED_MISSILE); - pbolt.flavour = BEAM_MMISSILE; // unresistable - pbolt.obvious_effect = true; - break; + { + ZAP_BONE_SHARDS, + "spray of bone shards", + // Incoming power is highly dependant on mass (see spells3.cc). + // Basic function is power * 15 + mass... with the largest + // available mass (3000) we get a power of 4500 at a power + // level of 100 (for 3d20). + 10000, + new dicedef_calculator<3, 2, 1, 250>, + new tohit_calculator<8, 1, 100>, + LIGHTGREY, + false, + BEAM_MAGIC, + DCHAR_FIRED_ZAP, + true, + true, + false + }, - case ZAP_POISON_ARROW: // cap 150 - pbolt.name = "poison arrow"; - pbolt.colour = LIGHTGREEN; - pbolt.damage = calc_dice( 4, 15 + power ); - pbolt.hit = 5 + power / 10; // 50: 10 100: 15 - pbolt.type = dchar_glyph(DCHAR_FIRED_MISSILE); - pbolt.flavour = BEAM_POISON_ARROW; // extra damage - pbolt.obvious_effect = true; - break; + { + ZAP_BANISHMENT, + "0", + 100, + NULL, + NULL, + BLACK, + true, + BEAM_BANISH, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_DISINTEGRATION: // cap 150 - pbolt.name = "0"; - pbolt.flavour = BEAM_DISINTEGRATION; - pbolt.damage = calc_dice( 3, 15 + (power * 3) / 4 ); - pbolt.ench_power *= 5; - pbolt.ench_power /= 2; - pbolt.is_beam = true; - break; + { + ZAP_DEGENERATION, + "0", + 100, + NULL, + NULL, + BLACK, + true, + BEAM_DEGENERATE, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_LIGHTNING: // cap 150 - // also for breath (at pow = lev * 2; max dam: 33) - pbolt.name = "bolt of lightning"; - pbolt.colour = LIGHTCYAN; - pbolt.damage = calc_dice( 1, 10 + (power * 3) / 5 ); - pbolt.hit = 7 + random2(power) / 20; // 50: 7-9 100: 7-12 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_ELECTRICITY; // beams & reflects - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; - case ZAP_FIREBALL: // cap 150 - pbolt.name = "fireball"; - pbolt.colour = RED; - pbolt.damage = calc_dice( 3, 10 + power / 2 ); - pbolt.hit = 40; // hit: 40 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_FIRE; // fire - pbolt.is_explosion = true; - break; + { + ZAP_STING, + "sting", + 25, + new dicedef_calculator<1, 3, 1, 5>, + new tohit_calculator<8, 1, 5>, + GREEN, + false, + BEAM_POISON, + DCHAR_FIRED_ZAP, + true, + false, + false + }, - case ZAP_ORB_OF_ELECTRICITY: // cap 150 - pbolt.name = "orb of electricity"; - pbolt.colour = LIGHTBLUE; - pbolt.damage = calc_dice( 1, 15 + (power * 4) / 5 ); - pbolt.damage.num = 0; // only does explosion damage - pbolt.hit = 40; // hit: 40 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_ELECTRICITY; - pbolt.is_explosion = true; - break; - case ZAP_ORB_OF_FRAGMENTATION: // cap 150 - pbolt.name = "metal orb"; - pbolt.colour = CYAN; - pbolt.damage = calc_dice( 3, 30 + (power * 3) / 4 ); - pbolt.hit = 20; // hit: 20 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_FRAG; // extra AC resist - pbolt.is_explosion = true; - break; + { + ZAP_HELLFIRE, + "hellfire", + 200, + new calcdice_calculator<3, 10, 3, 4>, + new tohit_calculator<20, 1, 10>, + RED, + false, + BEAM_HELLFIRE, + DCHAR_FIRED_ZAP, + true, + false, + true + }, - case ZAP_CLEANSING_FLAME: - pbolt.name = "golden flame"; - pbolt.colour = YELLOW; - pbolt.damage = calc_dice( 2, 20 + (power * 2) / 3 ); - pbolt.hit = 150; - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_HOLY; - pbolt.obvious_effect = true; - pbolt.is_explosion = true; - break; + { + ZAP_IRON_BOLT, + "iron bolt", + 200, + new calcdice_calculator<9, 15, 3, 4>, + new tohit_calculator<7, 1, 15>, + LIGHTCYAN, + false, + BEAM_MMISSILE, + DCHAR_FIRED_MISSILE, + true, + false, + false + }, - case ZAP_CRYSTAL_SPEAR: // cap 200 - pbolt.name = "crystal spear"; - pbolt.colour = WHITE; - pbolt.damage = calc_dice( 10, 23 + power ); - pbolt.hit = 10 + power / 15; // 50: 13 100: 16 - pbolt.type = dchar_glyph(DCHAR_FIRED_MISSILE); - pbolt.flavour = BEAM_MMISSILE; // unresistable - pbolt.obvious_effect = true; - break; + { + ZAP_STRIKING, + "force bolt", + 25, + new dicedef_calculator<1, 5, 0, 1>, + new tohit_calculator<8, 1, 10>, + BLACK, + false, + BEAM_MMISSILE, + DCHAR_SPACE, + true, + false, + false + }, - case ZAP_HELLFIRE: // cap 200 - pbolt.name = "hellfire"; - pbolt.colour = RED; - pbolt.damage = calc_dice( 3, 10 + (power * 3) / 4 ); - pbolt.hit = 20 + power / 10; // 50: 25 100: 30 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_HELLFIRE; - pbolt.obvious_effect = true; - pbolt.is_explosion = true; - break; + { + ZAP_STONE_ARROW, + "stone arrow", + 50, + new dicedef_calculator<2, 5, 1, 7>, + new tohit_calculator<8, 1, 10>, + LIGHTGREY, + false, + BEAM_MMISSILE, + DCHAR_FIRED_MISSILE, + true, + false, + false + }, - case ZAP_ICE_STORM: // cap 200 - pbolt.name = "great blast of cold"; - pbolt.colour = BLUE; - pbolt.damage = calc_dice( 7, 22 + power ); - pbolt.hit = 20 + power / 10; // 50: 25 100: 30 - pbolt.ench_power = power; // used for radius - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_ICE; // half resisted - pbolt.is_explosion = true; - break; + { + ZAP_ELECTRICITY, + "zap", + 25, + new dicedef_calculator<1, 3, 1, 4>, + new tohit_calculator<8, 1, 7>, + LIGHTCYAN, + false, + BEAM_ELECTRICITY, // beams & reflects + DCHAR_FIRED_ZAP, + true, + true, + false + }, - case ZAP_BEAM_OF_ENERGY: // bolt of innacuracy - pbolt.name = "narrow beam of energy"; - pbolt.colour = YELLOW; - pbolt.damage = calc_dice( 12, 40 + (power * 3) / 2 ); - pbolt.hit = 1; - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_ENERGY; // unresisted - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; + { + ZAP_ORB_OF_ELECTRICITY, + "orb of electricity", + 200, + new calcdice_calculator<0, 15, 4, 5>, + new tohit_calculator<40>, + LIGHTBLUE, + false, + BEAM_ELECTRICITY, + DCHAR_FIRED_ZAP, + true, + false, + true + }, - case ZAP_SPIT_POISON: // cap 50 - // max pow = lev + mut * 5 = 42 - pbolt.name = "splash of poison"; - pbolt.colour = GREEN; - pbolt.damage = dice_def( 1, 4 + power / 2 ); // max dam: 25 - pbolt.hit = 5 + random2( 1 + power / 3 ); // max hit: 19 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_POISON; - pbolt.obvious_effect = true; - break; + { + ZAP_SPIT_POISON, + "splash of poison", + 50, + new dicedef_calculator<1, 4, 1, 2>, + new tohit_calculator<5, 1, 6>, + GREEN, + false, + BEAM_POISON, + DCHAR_FIRED_ZAP, + true, + false, + false + }, - case ZAP_BREATHE_FIRE: // cap 50 - // max pow = lev + mut * 4 + 12 = 51 (capped to 50) - pbolt.name = "fiery breath"; - pbolt.colour = RED; - pbolt.damage = dice_def( 3, 4 + power / 3 ); // max dam: 60 - pbolt.hit = 8 + random2( 1 + power / 3 ); // max hit: 25 - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_FIRE; - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; + { + ZAP_DEBUGGING_RAY, + "debugging ray", + 10000, + new dicedef_calculator<1500, 1, 0, 1>, + new tohit_calculator<1500>, + WHITE, + false, + BEAM_MMISSILE, + DCHAR_FIRED_DEBUG, + true, + false, + false + }, - case ZAP_BREATHE_FROST: // cap 50 - // max power = lev = 27 - pbolt.name = "freezing breath"; - pbolt.colour = WHITE; - pbolt.damage = dice_def( 3, 4 + power / 3 ); // max dam: 39 - pbolt.hit = 8 + random2( 1 + power / 3 ); - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_COLD; - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; + { + ZAP_BREATHE_FIRE, + "fiery breath", + 50, + new dicedef_calculator<3, 4, 1, 3>, + new tohit_calculator<8, 1, 6>, + RED, + false, + BEAM_FIRE, + DCHAR_FIRED_ZAP, + true, + true, + false + }, - case ZAP_BREATHE_ACID: // cap 50 - // max power = lev for ability, 50 for minor destruction (max dam: 57) - pbolt.name = "acid"; - pbolt.colour = YELLOW; - pbolt.damage = dice_def( 3, 3 + power / 3 ); // max dam: 36 - pbolt.hit = 5 + random2( 1 + power / 3 ); - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_ACID; - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; - case ZAP_BREATHE_POISON: // leaves clouds of gas // cap 50 - // max power = lev = 27 - pbolt.name = "poison gas"; - pbolt.colour = GREEN; - pbolt.damage = dice_def( 3, 2 + power / 6 ); // max dam: 18 - pbolt.hit = 6 + random2( 1 + power / 3 ); - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_POISON; - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; + { + ZAP_BREATHE_FROST, + "freezing breath", + 50, + new dicedef_calculator<3, 4, 1, 3>, + new tohit_calculator<8, 1, 6>, + WHITE, + false, + BEAM_COLD, + DCHAR_FIRED_ZAP, + true, + true, + false + }, - case ZAP_BREATHE_POWER: // cap 50 - pbolt.name = "bolt of energy"; - // max power = lev = 27 - - pbolt.colour = BLUE; - if (random2(power) >= 8) - pbolt.colour = LIGHTBLUE; - if (random2(power) >= 12) - pbolt.colour = MAGENTA; - if (random2(power) >= 17) - pbolt.colour = LIGHTMAGENTA; - - pbolt.damage = dice_def( 3, 3 + power / 3 ); // max dam: 36 - pbolt.hit = 5 + random2( 1 + power / 3 ); - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_MMISSILE; // unresistable - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; + { + ZAP_BREATHE_ACID, + "acid", + 50, + new dicedef_calculator<3, 3, 1, 3>, + new tohit_calculator<5, 1, 6>, + YELLOW, + false, + BEAM_ACID, + DCHAR_FIRED_ZAP, + true, + true, + false + }, - case ZAP_BREATHE_STEAM: // cap 50 - // max power = lev = 27 - pbolt.name = "ball of steam"; - pbolt.colour = LIGHTGREY; - pbolt.damage = dice_def( 3, 4 + power / 5 ); // max dam: 27 - pbolt.hit = 10 + random2( 1 + power / 5 ); - pbolt.type = dchar_glyph(DCHAR_FIRED_ZAP); - pbolt.flavour = BEAM_STEAM; - pbolt.obvious_effect = true; - pbolt.is_beam = true; - break; + { + ZAP_BREATHE_POISON, + "poison gas", + 50, + new dicedef_calculator<3, 2, 1, 6>, + new tohit_calculator<6, 1, 6>, + GREEN, + false, + BEAM_POISON, + DCHAR_FIRED_ZAP, + true, + true, + false + }, - case ZAP_SLOWING: - pbolt.name = "0"; - pbolt.flavour = BEAM_SLOW; - // pbolt.is_beam = true; - break; + { + ZAP_BREATHE_POWER, + "bolt of energy", + 50, + new dicedef_calculator<3, 3, 1, 3>, + new tohit_calculator<5, 1, 6>, + BLUE, + false, + BEAM_MMISSILE, + DCHAR_FIRED_ZAP, + true, + true, + false + }, - case ZAP_HASTING: - pbolt.name = "0"; - pbolt.flavour = BEAM_HASTE; - // pbolt.is_beam = true; - break; + { + ZAP_ENSLAVE_UNDEAD, + "0", + 100, + NULL, + NULL, + BLACK, + true, + BEAM_ENSLAVE_UNDEAD, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_PARALYSIS: - pbolt.name = "0"; - pbolt.flavour = BEAM_PARALYSIS; - // pbolt.is_beam = true; - break; + { + ZAP_AGONY, + "0agony", + 100, + NULL, + new tohit_calculator<0, 5, 1>, + BLACK, + true, + BEAM_PAIN, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_PETRIFY: - pbolt.name = "0"; - pbolt.flavour = BEAM_PETRIFY; - // pbolt.is_beam = true; - break; - case ZAP_CONFUSION: - pbolt.name = "0"; - pbolt.flavour = BEAM_CONFUSION; - // pbolt.is_beam = true; - break; + { + ZAP_DISRUPTION, + "0", + 100, + new dicedef_calculator<1, 4, 1, 5>, + new tohit_calculator<0, 3, 1>, + BLACK, + true, + BEAM_DISINTEGRATION, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_INVISIBILITY: - pbolt.name = "0"; - pbolt.flavour = BEAM_INVISIBILITY; - // pbolt.is_beam = true; - break; + { + ZAP_DISINTEGRATION, + "0", + 100, + new calcdice_calculator<3, 15, 3, 4>, + new tohit_calculator<0, 5, 2>, + BLACK, + true, + BEAM_DISINTEGRATION, + DCHAR_SPACE, + false, + true, + false + }, + + { + ZAP_BREATHE_STEAM, + "ball of steam", + 50, + new dicedef_calculator<3, 4, 1, 5>, + new tohit_calculator<10, 1, 10>, + LIGHTGREY, + false, + BEAM_STEAM, + DCHAR_FIRED_ZAP, + true, + true, + false + }, - case ZAP_HEALING: - pbolt.name = "0"; - pbolt.flavour = BEAM_HEALING; - pbolt.damage = dice_def( 1, 7 + power / 3 ); - // pbolt.is_beam = true; - break; + { + ZAP_CONTROL_DEMON, + "0", + 100, + NULL, + new tohit_calculator<0, 3, 2>, + BLACK, + true, + BEAM_ENSLAVE_DEMON, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_DIGGING: - pbolt.name = "0"; - pbolt.flavour = BEAM_DIGGING; - // not ordinary "0" beam range {dlb} - pbolt.is_beam = true; - break; + { + ZAP_ORB_OF_FRAGMENTATION, + "metal orb", + 200, + new calcdice_calculator<3, 30, 3, 4>, + new tohit_calculator<20>, + CYAN, + false, + BEAM_FRAG, + DCHAR_FIRED_ZAP, + false, + false, + true + }, - case ZAP_TELEPORTATION: - pbolt.name = "0"; - pbolt.flavour = BEAM_TELEPORT; - // pbolt.is_beam = true; - break; + { + ZAP_ICE_BOLT, + "bolt of ice", + 100, + new calcdice_calculator<3, 10, 1, 2>, + new tohit_calculator<9, 1, 12>, + WHITE, + false, + BEAM_ICE, + DCHAR_FIRED_ZAP, + false, + false, + false + }, + + { // ench_power controls radius + ZAP_ICE_STORM, + "great blast of cold", + 200, + new calcdice_calculator<7, 22, 1, 1>, + new tohit_calculator<20, 1, 10>, + BLUE, + false, + BEAM_ICE, + DCHAR_FIRED_ZAP, + true, + false, + true + }, - case ZAP_POLYMORPH_OTHER: - pbolt.name = "0"; - pbolt.flavour = BEAM_POLYMORPH; - // pbolt.is_beam = true; - break; + { + ZAP_BACKLIGHT, + "0", + 100, + NULL, + NULL, + BLUE, + true, + BEAM_BACKLIGHT, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_ENSLAVEMENT: - pbolt.name = "0"; - pbolt.flavour = BEAM_CHARM; - // pbolt.is_beam = true; - break; + { + ZAP_SLEEP, + "0", + 100, + NULL, + NULL, + BLACK, + true, + BEAM_SLEEP, + DCHAR_SPACE, + false, + false, + false + }, - case ZAP_BANISHMENT: - pbolt.name = "0"; - pbolt.flavour = BEAM_BANISH; - // pbolt.is_beam = true; - break; + { + ZAP_FLAME_TONGUE, + "flame", + 25, + new dicedef_calculator<1, 8, 1, 4>, + new tohit_calculator<7, 1, 6>, + RED, + false, + BEAM_FIRE, + DCHAR_FIRED_BOLT, + true, + false, + false + }, - case ZAP_DEGENERATION: - pbolt.name = "0"; - pbolt.flavour = BEAM_DEGENERATE; - // pbolt.is_beam = true; - break; + { + ZAP_SANDBLAST, + "rocky blast", + 50, + new dicedef_calculator<2, 4, 1, 3>, + new tohit_calculator<13, 1, 10>, + BROWN, + false, + BEAM_FRAG, + DCHAR_FIRED_BOLT, + true, + false, + false + }, - case ZAP_ENSLAVE_UNDEAD: - pbolt.name = "0"; - pbolt.flavour = BEAM_ENSLAVE_UNDEAD; - // pbolt.is_beam = true; - break; + { + ZAP_SMALL_SANDBLAST, + "blast of sand", + 25, + new dicedef_calculator<1, 8, 1, 4>, + new tohit_calculator<8, 1, 5>, + BROWN, + false, + BEAM_FRAG, + DCHAR_FIRED_BOLT, + true, + false, + false + }, - case ZAP_AGONY: - pbolt.name = "0agony"; - pbolt.flavour = BEAM_PAIN; - pbolt.ench_power *= 5; - // pbolt.is_beam = true; - break; + { + ZAP_MAGMA, + "bolt of magma", + 200, + new calcdice_calculator<4, 10, 3, 5>, + new tohit_calculator<8, 1, 25>, + RED, + false, + BEAM_LAVA, + DCHAR_FIRED_ZAP, + true, + true, + false + }, - case ZAP_CONTROL_DEMON: - pbolt.name = "0"; - pbolt.flavour = BEAM_ENSLAVE_DEMON; - pbolt.ench_power *= 3; - pbolt.ench_power /= 2; - // pbolt.is_beam = true; - break; + { + ZAP_POISON_ARROW, + "poison arrow", + 200, + new calcdice_calculator<4, 15, 1, 1>, + new tohit_calculator<5, 1, 10>, + LIGHTGREEN, + false, + BEAM_POISON_ARROW, // extra damage + DCHAR_FIRED_MISSILE, + true, + false, + false + }, - case ZAP_SLEEP: //jmf: added - pbolt.name = "0"; - pbolt.flavour = BEAM_SLEEP; - // pbolt.is_beam = true; - break; + { + ZAP_PETRIFY, + "0", + 100, + NULL, + NULL, + BLACK, + true, + BEAM_PETRIFY, + DCHAR_SPACE, + false, + false, + false + } +}; - case ZAP_BACKLIGHT: //jmf: added - pbolt.name = "0"; - pbolt.flavour = BEAM_BACKLIGHT; - pbolt.colour = BLUE; - // pbolt.is_beam = true; - break; - case ZAP_DEBUGGING_RAY: - pbolt.name = "debugging ray"; - pbolt.colour = random_colour(); - pbolt.damage = dice_def( 1500, 1 ); // dam: 1500 - pbolt.hit = 1500; // hit: 1500 - pbolt.type = dchar_glyph(DCHAR_FIRED_DEBUG); - pbolt.flavour = BEAM_MMISSILE; // unresistable - pbolt.obvious_effect = true; - break; +// Need to see zapping() for default values not set within this function {dlb} +static void _zappy( zap_type z_type, int power, bolt &pbolt ) +{ + const zap_info* zinfo = NULL; - default: - pbolt.name = "buggy beam"; - pbolt.colour = random_colour(); - pbolt.damage = dice_def( 1, 0 ); - pbolt.hit = 60; - pbolt.type = dchar_glyph(DCHAR_FIRED_DEBUG); - pbolt.flavour = BEAM_MMISSILE; // unresistable - pbolt.obvious_effect = true; - break; + // Find the appropriate zap info. + for (unsigned int i = 0; i < ARRAYSZ(zap_data); ++i) + { + if (zap_data[i].ztype == z_type) + { + zinfo = &zap_data[i]; + break; + } + } + + // None found? + if (zinfo == NULL) + { +#ifdef DEBUG_DIAGNOSTICS + mprf(MSGCH_ERROR, "Couldn't find zap type %d", z_type); +#endif + return; + } + + // Fill + pbolt.name = zinfo->name; + pbolt.flavour = zinfo->flavour; + pbolt.colour = zinfo->colour; + pbolt.type = dchar_glyph(zinfo->glyph); + pbolt.obvious_effect = zinfo->always_obvious; + pbolt.is_beam = zinfo->can_beam; + pbolt.is_explosion = zinfo->is_explosion; + + if (zinfo->power_cap > 0) + power = std::min(zinfo->power_cap, power); + + ASSERT(zinfo->is_enchantment == pbolt.is_enchantment()); + + if (zinfo->is_enchantment) + { + pbolt.ench_power = (zinfo->tohit ? (*zinfo->tohit)(power) : power); + pbolt.hit = AUTOMATIC_HIT; + } + else + { + pbolt.hit = (*zinfo->tohit)(power); + if (wearing_amulet(AMU_INACCURACY)) + pbolt.hit = std::max(0, pbolt.hit - 5); } - if (wearing_amulet(AMU_INACCURACY)) - pbolt.hit = std::max(0, pbolt.hit - 5); + if (zinfo->damage) + pbolt.damage = (*zinfo->damage)(power); + + // One special case + if (z_type == ZAP_ICE_STORM) + pbolt.ench_power = power; // used for radius } // Affect monster in wall unless it can shield itself using the wall. @@ -4850,37 +4712,8 @@ static int _range_used_on_hit(bolt &beam) if (!beam.is_beam) return (BEAM_STOP); - // CHECK ENCHANTMENTS if (beam.is_enchantment()) - { - switch(beam.flavour) - { - case BEAM_SLOW: - case BEAM_HASTE: - case BEAM_HEALING: - case BEAM_PARALYSIS: - case BEAM_PETRIFY: - case BEAM_CONFUSION: - case BEAM_INVISIBILITY: - case BEAM_TELEPORT: - case BEAM_POLYMORPH: - case BEAM_CHARM: - case BEAM_BANISH: - case BEAM_PAIN: - case BEAM_DISINTEGRATION: - case BEAM_DEGENERATE: - case BEAM_DISPEL_UNDEAD: - case BEAM_ENSLAVE_UNDEAD: - case BEAM_ENSLAVE_DEMON: - case BEAM_SLEEP: - case BEAM_BACKLIGHT: - return (BEAM_STOP); - default: - break; - } - - return (0); - } + return (beam.flavour == BEAM_DIGGING ? 0 : BEAM_STOP); // Hellfire stops for nobody! if (beam.name == "hellfire") diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index a920d89b38..d4c41758c8 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -438,11 +438,7 @@ static void _push_top_card(item_def& deck, card_type card, static bool _wielding_deck() { - // Nothing wielded? - if (you.equip[EQ_WEAPON] == -1) - return (false); - - return is_deck(you.inv[you.equip[EQ_WEAPON]]); + return (you.weapon() && is_deck(*you.weapon())); } static void _remember_drawn_card(item_def& deck, card_type card, bool allow_id) @@ -941,7 +937,7 @@ bool deck_stack() crawl_state.zero_turns_taken(); return (false); } - item_def& deck(you.inv[you.equip[EQ_WEAPON]]); + item_def& deck(*you.weapon()); if (_check_buggy_deck(deck)) return (false); diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc index 895fb4646f..798bf65a89 100644 --- a/crawl-ref/source/effects.cc +++ b/crawl-ref/source/effects.cc @@ -670,10 +670,10 @@ void random_uselessness(int scroll_slot) break; case 2: - if (you.equip[EQ_WEAPON] != -1) + if (you.weapon()) { mprf("%s glows %s for a moment.", - you.inv[you.equip[EQ_WEAPON]].name(DESC_CAP_YOUR).c_str(), + you.weapon()->name(DESC_CAP_YOUR).c_str(), weird_glowing_colour().c_str()); } else @@ -2524,14 +2524,14 @@ void handle_time(long time_delta) // Random chance to identify staff in hand based off of Spellcasting // and an appropriate other spell skill... is 1/20 too fast? - if (you.equip[EQ_WEAPON] != -1 - && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_STAVES - && !item_type_known( you.inv[you.equip[EQ_WEAPON]] ) + if (you.weapon() + && you.weapon()->base_type == OBJ_STAVES + && !item_type_known(*you.weapon()) && one_chance_in(20)) { int total_skill = you.skills[SK_SPELLCASTING]; - switch (you.inv[you.equip[EQ_WEAPON]].sub_type) + switch (you.weapon()->sub_type) { case STAFF_WIZARDRY: case STAFF_ENERGY: @@ -2580,10 +2580,10 @@ void handle_time(long time_delta) if (x_chance_in_y(total_skill, 100)) { - item_def& item = you.inv[you.equip[EQ_WEAPON]]; + item_def& item = *you.weapon(); - set_ident_type( OBJ_STAVES, item.sub_type, ID_KNOWN_TYPE ); - set_ident_flags( item, ISFLAG_IDENT_MASK ); + set_ident_type(OBJ_STAVES, item.sub_type, ID_KNOWN_TYPE); + set_ident_flags(item, ISFLAG_IDENT_MASK); mprf("You are wielding %s.", item.name(DESC_NOCAP_A).c_str()); more(); diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index 93f2dc684f..13acab5ed4 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -198,8 +198,6 @@ enum beam_type // beam[].flavour BEAM_HOLY, BEAM_FRAG, BEAM_LAVA, - BEAM_BACKLIGHT, - BEAM_SLEEP, BEAM_ICE, BEAM_NUKE, BEAM_RANDOM, // 25 - currently translates into FIRE..ACID @@ -225,6 +223,8 @@ enum beam_type // beam[].flavour BEAM_ENSLAVE_DEMON, BEAM_BLINK, BEAM_PETRIFY, + BEAM_BACKLIGHT, + BEAM_SLEEP, BEAM_LAST_ENCHANTMENT = BEAM_PETRIFY, // new beams for evaporate diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc index 8a73d1aa84..e42bb09e33 100644 --- a/crawl-ref/source/food.cc +++ b/crawl-ref/source/food.cc @@ -364,8 +364,7 @@ static void _terminate_butchery(bool wpn_switch, bool removed_gloves, { // Switch weapon back. if (wpn_switch && you.equip[EQ_WEAPON] != old_weapon - && (you.equip[EQ_WEAPON] == -1 - || !item_cursed(you.inv[you.equip[EQ_WEAPON]]))) + && (!you.weapon() || !item_cursed(*you.weapon()))) { start_delay( DELAY_WEAPON_SWAP, 1, old_weapon ); } @@ -475,8 +474,7 @@ bool butchery(int which_corpse) && !item_cursed(you.inv[you.equip[EQ_GLOVES]])); bool can_butcher = teeth_butcher || barehand_butcher - || you.equip[EQ_WEAPON] != -1 - && can_cut_meat(you.inv[you.equip[EQ_WEAPON]]); + || (you.weapon() && can_cut_meat(*you.weapon())); if (!Options.easy_butcher && !can_butcher) { diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index 1e4cdf7141..b387d75e20 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -1167,13 +1167,13 @@ static bool _check_old_item_warning( const item_def& item, operation_types oper ) { item_def old_item; - std::string prompt = ""; + std::string prompt; if (oper == OPER_WIELD) // can we safely unwield old item? { - if (you.equip[EQ_WEAPON] == -1) + if (!you.weapon()) return (true); - old_item = you.inv[you.equip[EQ_WEAPON]]; + old_item = *you.weapon(); if (!has_warning_inscription(old_item, OPER_WIELD)) return (true); diff --git a/crawl-ref/source/it_use3.cc b/crawl-ref/source/it_use3.cc index c38df3aa6f..dbc5900f2f 100644 --- a/crawl-ref/source/it_use3.cc +++ b/crawl-ref/source/it_use3.cc @@ -1006,7 +1006,7 @@ static bool box_of_beasts() else { mpr("...but the box appears empty."); - you.inv[you.equip[EQ_WEAPON]].sub_type = MISC_EMPTY_EBONY_CASKET; + you.weapon()->sub_type = MISC_EMPTY_EBONY_CASKET; } } diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc index 4d3179566c..8ae9be4044 100644 --- a/crawl-ref/source/item_use.cc +++ b/crawl-ref/source/item_use.cc @@ -92,9 +92,9 @@ bool can_wield(item_def *weapon, bool say_reason, } if (!ignore_temporary_disability - && you.equip[EQ_WEAPON] != -1 - && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS - && item_cursed( you.inv[you.equip[EQ_WEAPON]] )) + && you.weapon() + && you.weapon()->base_type == OBJ_WEAPONS + && item_cursed(*you.weapon())) { SAY(mpr("You can't unwield your weapon to draw a new one!")); return (false); @@ -1075,12 +1075,10 @@ bool do_wear_armour( int item, bool quiet ) return (!takeoff_armour(item)); // if you're wielding something, - if (you.equip[EQ_WEAPON] != -1 + if (you.weapon() // attempting to wear a shield, && is_shield(you.inv[item]) - && is_shield_incompatible( - you.inv[you.equip[EQ_WEAPON]], - &you.inv[item])) + && is_shield_incompatible(*you.weapon(), &you.inv[item])) { if (!quiet) mpr("You'd need three hands to do that!"); @@ -2030,7 +2028,7 @@ bool throw_it(bolt &pbolt, int throw_2, bool teleport, int acc_bonus, // CALCULATIONS FOR LAUNCHED WEAPONS if (projected == LRET_LAUNCHED) { - const item_def &launcher = you.inv[you.equip[EQ_WEAPON]]; + const item_def &launcher = *you.weapon(); // Extract launcher bonuses due to magic. lnchHitBonus = launcher.plus; @@ -2071,17 +2069,15 @@ bool throw_it(bolt &pbolt, int throw_2, bool teleport, int acc_bonus, ammoDamBonus = ammoHitBonus; // Check for matches; dwarven, elven, orcish. - if (!get_equip_race(you.inv[you.equip[EQ_WEAPON]]) == 0) + if (!(get_equip_race(*you.weapon()) == 0)) { - if (get_equip_race(you.inv[you.equip[EQ_WEAPON]]) - == get_equip_race(item)) + if (get_equip_race(*you.weapon()) == get_equip_race(item)) { baseHit++; baseDam++; // elves with elven bows - if (get_equip_race(you.inv[you.equip[EQ_WEAPON]]) - == ISFLAG_ELVEN + if (get_equip_race(*you.weapon()) == ISFLAG_ELVEN && player_genus(GENPC_ELVEN)) { baseHit++; @@ -2259,7 +2255,7 @@ bool throw_it(bolt &pbolt, int throw_2, bool teleport, int acc_bonus, // ID check. Can't ID off teleported projectiles, uh, because // it's too weird. Also it messes up the messages. - if (item_ident(you.inv[you.equip[EQ_WEAPON]], ISFLAG_KNOW_PLUSES)) + if (item_ident(*you.weapon(), ISFLAG_KNOW_PLUSES)) { if (!teleport && !item_ident(you.inv[throw_2], ISFLAG_KNOW_PLUSES) @@ -2274,7 +2270,7 @@ bool throw_it(bolt &pbolt, int throw_2, bool teleport, int acc_bonus, } else if (!teleport && x_chance_in_y(shoot_skill, 100)) { - item_def& weapon = you.inv[you.equip[EQ_WEAPON]]; + item_def& weapon = *you.weapon(); set_ident_flags(weapon, ISFLAG_KNOW_PLUSES); mprf("You are wielding %s.", weapon.name(DESC_NOCAP_A).c_str()); diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc index caf554bdfd..8ef197979a 100644 --- a/crawl-ref/source/mstuff2.cc +++ b/crawl-ref/source/mstuff2.cc @@ -1527,7 +1527,7 @@ bolt mons_spells( monsters *mons, spell_type spell_cast, int power ) beam.hit = 40; beam.type = dchar_glyph(DCHAR_FIRED_ZAP); beam.thrower = KILL_MON; - beam.flavour = BEAM_FIRE; // why not BEAM_FIRE? {dlb} + beam.flavour = BEAM_FIRE; beam.is_beam = false; beam.is_explosion = true; break; diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index bde08f20da..dbee402827 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -5220,8 +5220,7 @@ bool _give_items_skills() you.skills[SK_UNARMED_COMBAT] = weap_skill; else { - you.skills[weapon_skill(you.inv[you.equip[EQ_WEAPON]])] - = weap_skill; + you.skills[weapon_skill(*you.weapon())] = weap_skill; } } diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 588e95280e..8e61018fdc 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -702,10 +702,10 @@ int get_player_wielded_weapon() // Returns false if the player is wielding a weapon inappropriate for Berserk. bool berserk_check_wielded_weapon() { - if (you.equip[EQ_WEAPON] == -1) + if (!you.weapon()) return (true); - const item_def weapon = you.inv[you.equip[EQ_WEAPON]]; + const item_def weapon = *you.weapon(); if (is_valid_item(weapon) && weapon.base_type != OBJ_STAVES && (weapon.base_type != OBJ_WEAPONS || is_range_weapon(weapon)) || you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED]) @@ -736,21 +736,20 @@ int player_equip( equipment_type slot, int sub_type, bool calc_unid ) { case EQ_WEAPON: // Hands can have more than just weapons. - if (you.equip[EQ_WEAPON] != -1 - && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS - && you.inv[you.equip[EQ_WEAPON]].sub_type == sub_type) + if (you.weapon() + && you.weapon()->base_type == OBJ_WEAPONS + && you.weapon()->sub_type == sub_type) { ret++; } break; case EQ_STAFF: - // Like above, but must be magical stave. - if (you.equip[EQ_WEAPON] != -1 - && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_STAVES - && you.inv[you.equip[EQ_WEAPON]].sub_type == sub_type - && (calc_unid - || item_type_known( you.inv[you.equip[EQ_WEAPON]] ))) + // Like above, but must be magical staff. + if (you.weapon() + && you.weapon()->base_type == OBJ_STAVES + && you.weapon()->sub_type == sub_type + && (calc_unid || item_type_known(*you.weapon()))) { ret++; } @@ -903,9 +902,9 @@ int player_teleport(bool calc_unid) tp += player_mutation_level(MUT_TELEPORT) * 3; // randart weapons only - if (you.equip[EQ_WEAPON] != -1 - && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS - && is_random_artefact( you.inv[you.equip[EQ_WEAPON]] )) + if (you.weapon() + && you.weapon()->base_type == OBJ_WEAPONS + && is_random_artefact(*you.weapon())) { tp += scan_randarts(RAP_CAUSE_TELEPORTATION, calc_unid); } @@ -1482,9 +1481,9 @@ int player_res_poison(bool calc_unid, bool temp, bool items) rp += player_equip( EQ_STAFF, STAFF_POISON, calc_unid ); // the staff of Olgreb: - if (you.equip[EQ_WEAPON] != -1 - && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS - && you.inv[you.equip[EQ_WEAPON]].special == SPWPN_STAFF_OF_OLGREB) + if (you.weapon() + && you.weapon()->base_type == OBJ_WEAPONS + && you.weapon()->special == SPWPN_STAFF_OF_OLGREB) { rp++; } @@ -1677,9 +1676,9 @@ int player_spec_poison() /* Staves */ sp += player_equip( EQ_STAFF, STAFF_POISON ); - if (you.equip[EQ_WEAPON] != -1 - && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS - && you.inv[you.equip[EQ_WEAPON]].special == SPWPN_STAFF_OF_OLGREB) + if (you.weapon() + && you.weapon()->base_type == OBJ_WEAPONS + && you.weapon()->special == SPWPN_STAFF_OF_OLGREB) { sp++; } diff --git a/crawl-ref/source/skills.cc b/crawl-ref/source/skills.cc index a7ff0beb02..112ce5b4c2 100644 --- a/crawl-ref/source/skills.cc +++ b/crawl-ref/source/skills.cc @@ -449,11 +449,8 @@ static int _exercise2(int exsk) if (best != old_best_skill || old_best_skill == exsk) redraw_skill( you.your_name, player_title() ); - if (you.equip[EQ_WEAPON] != -1 - && item_is_staff( you.inv[you.equip[EQ_WEAPON]] )) - { - maybe_identify_staff(you.inv[you.equip[EQ_WEAPON]]); - } + if (you.weapon() && item_is_staff( *you.weapon() )) + maybe_identify_staff(*you.weapon()); } return (skill_inc); diff --git a/crawl-ref/source/spells1.cc b/crawl-ref/source/spells1.cc index 56a49cff5c..04274d833e 100644 --- a/crawl-ref/source/spells1.cc +++ b/crawl-ref/source/spells1.cc @@ -1498,10 +1498,10 @@ bool cast_sure_blade(int power) { bool success = false; - if (you.equip[EQ_WEAPON] == -1) + if (!you.weapon()) mpr("You aren't wielding a weapon!"); - else if (weapon_skill( you.inv[you.equip[EQ_WEAPON]].base_type, - you.inv[you.equip[EQ_WEAPON]].sub_type) != SK_SHORT_BLADES) + else if (weapon_skill(you.weapon()->base_type, + you.weapon()->sub_type) != SK_SHORT_BLADES) { mpr("You cannot bond with this weapon."); } diff --git a/crawl-ref/source/spells2.cc b/crawl-ref/source/spells2.cc index a9f7f9a4fd..466e6d4f8a 100644 --- a/crawl-ref/source/spells2.cc +++ b/crawl-ref/source/spells2.cc @@ -1033,48 +1033,42 @@ bool cast_summon_small_mammals(int pow, god_type god) bool cast_sticks_to_snakes(int pow, god_type god) { - const int wpn = you.equip[EQ_WEAPON]; - - if (wpn == -1) + if (!you.weapon()) { mprf("Your %s feel slithery!", your_hand(true).c_str()); return (false); } + const item_def& wpn = *you.weapon(); + // Don't enchant sticks marked with {!D}. - if (!check_warning_inscriptions(you.inv[wpn], OPER_DESTROY)) + if (!check_warning_inscriptions(wpn, OPER_DESTROY)) { mprf("%s feel%s slithery for a moment!", - you.inv[wpn].name(DESC_CAP_YOUR).c_str(), - you.inv[wpn].quantity > 1 ? "s" : ""); + wpn.name(DESC_CAP_YOUR).c_str(), + wpn.quantity > 1 ? "s" : ""); return (false); } monster_type mon = MONS_PROGRAM_BUG; const int dur = std::min(3 + random2(pow) / 20, 5); - int how_many_max = 1 + random2(1 + you.skills[SK_TRANSMIGRATION]) / 4; - - const bool friendly = (!item_cursed(you.inv[wpn])); - - const beh_type beha = (friendly) ? BEH_FRIENDLY - : BEH_HOSTILE; - const unsigned short hitting = (friendly) ? you.pet_target - : MHITYOU; + const bool friendly = (!item_cursed(wpn)); + const beh_type beha = (friendly) ? BEH_FRIENDLY : BEH_HOSTILE; + const unsigned short hitting = (friendly) ? you.pet_target : MHITYOU; int count = 0; - if (you.inv[wpn].base_type == OBJ_MISSILES - && you.inv[wpn].sub_type == MI_ARROW) + if (wpn.base_type == OBJ_MISSILES && wpn.sub_type == MI_ARROW) { - if (you.inv[wpn].quantity < how_many_max) - how_many_max = you.inv[wpn].quantity; + if (wpn.quantity < how_many_max) + how_many_max = wpn.quantity; for (int i = 0; i <= how_many_max; i++) { if (one_chance_in(5 - std::min(4, div_rand_round(pow * 2, 25))) - || get_ammo_brand(you.inv[wpn]) == SPMSL_POISONED) + || get_ammo_brand(wpn) == SPMSL_POISONED) { mon = x_chance_in_y(pow / 3, 100) ? MONS_BROWN_SNAKE : MONS_SNAKE; @@ -1092,19 +1086,19 @@ bool cast_sticks_to_snakes(int pow, god_type god) } } - if (you.inv[wpn].base_type == OBJ_WEAPONS - && (you.inv[wpn].sub_type == WPN_CLUB - || you.inv[wpn].sub_type == WPN_SPEAR - || you.inv[wpn].sub_type == WPN_QUARTERSTAFF - || you.inv[wpn].sub_type == WPN_SCYTHE - || you.inv[wpn].sub_type == WPN_GIANT_CLUB - || you.inv[wpn].sub_type == WPN_GIANT_SPIKED_CLUB - || you.inv[wpn].sub_type == WPN_BOW - || you.inv[wpn].sub_type == WPN_LONGBOW - || you.inv[wpn].sub_type == WPN_ANKUS - || you.inv[wpn].sub_type == WPN_HALBERD - || you.inv[wpn].sub_type == WPN_GLAIVE - || you.inv[wpn].sub_type == WPN_BLOWGUN)) + if (wpn.base_type == OBJ_WEAPONS + && (wpn.sub_type == WPN_CLUB + || wpn.sub_type == WPN_SPEAR + || wpn.sub_type == WPN_QUARTERSTAFF + || wpn.sub_type == WPN_SCYTHE + || wpn.sub_type == WPN_GIANT_CLUB + || wpn.sub_type == WPN_GIANT_SPIKED_CLUB + || wpn.sub_type == WPN_BOW + || wpn.sub_type == WPN_LONGBOW + || wpn.sub_type == WPN_ANKUS + || wpn.sub_type == WPN_HALBERD + || wpn.sub_type == WPN_GLAIVE + || wpn.sub_type == WPN_BLOWGUN)) { // Upsizing Snakes to Brown Snakes as the base class for using // the really big sticks (so bonus applies really only to trolls, @@ -1112,7 +1106,7 @@ bool cast_sticks_to_snakes(int pow, god_type god) // any character is strong enough to bother lugging a few of // these around. -- bwr - if (item_mass(you.inv[wpn]) < 300) + if (item_mass(wpn) < 300) mon = MONS_SNAKE; else mon = MONS_BROWN_SNAKE; @@ -1138,7 +1132,8 @@ bool cast_sticks_to_snakes(int pow, god_type god) } } - count = MIN(count, you.inv[you.equip[EQ_WEAPON]].quantity); + if (wpn.quantity < count) + count = wpn.quantity; if (count > 0) { diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc index 8739c7f965..4bccb6e4e4 100644 --- a/crawl-ref/source/spells3.cc +++ b/crawl-ref/source/spells3.cc @@ -118,29 +118,25 @@ bool cast_selective_amnesia(bool force) bool remove_curse(bool suppress_msg) { - int loopy = 0; // general purpose loop variable {dlb} - bool success = false; // whether or not curse(s) removed {dlb} + bool success = false; - // Special "wield slot" case - see if you can figure out why {dlb}: - // ... because only cursed *weapons* in hand count as cursed -- bwr - if (you.equip[EQ_WEAPON] != -1 - && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS) + // Only cursed *weapons* in hand count as cursed -- bwr + if (you.weapon() + && you.weapon()->base_type == OBJ_WEAPONS + && item_cursed(*you.weapon())) { - if (item_cursed( you.inv[you.equip[EQ_WEAPON]] )) - { - // Also sets wield_change. - do_uncurse_item( you.inv[you.equip[EQ_WEAPON]] ); - success = true; - } + // Also sets wield_change. + do_uncurse_item(*you.weapon()); + success = true; } // Everything else uses the same paradigm - are we certain? // What of artefact rings and amulets? {dlb}: - for (loopy = EQ_CLOAK; loopy < NUM_EQUIP; loopy++) + for (int i = EQ_WEAPON + 1; i < NUM_EQUIP; i++) { - if (you.equip[loopy] != -1 && item_cursed(you.inv[you.equip[loopy]])) + if (you.equip[i] != -1 && item_cursed(you.inv[you.equip[i]])) { - do_uncurse_item( you.inv[you.equip[loopy]] ); + do_uncurse_item( you.inv[you.equip[i]] ); success = true; } } @@ -159,20 +155,21 @@ bool remove_curse(bool suppress_msg) bool detect_curse(bool suppress_msg) { - int loopy = 0; // general purpose loop variable {dlb} bool success = false; // whether or not any curses found {dlb} - for (loopy = 0; loopy < ENDOFPACK; loopy++) + for (int i = 0; i < ENDOFPACK; i++) { - if (you.inv[loopy].quantity - && (you.inv[loopy].base_type == OBJ_WEAPONS - || you.inv[loopy].base_type == OBJ_ARMOUR - || you.inv[loopy].base_type == OBJ_JEWELLERY)) + item_def& item = you.inv[i]; + + if (is_valid_item(item) + && (item.base_type == OBJ_WEAPONS + || item.base_type == OBJ_ARMOUR + || item.base_type == OBJ_JEWELLERY)) { - if (!item_ident( you.inv[loopy], ISFLAG_KNOW_CURSE )) + if (!item_ident(item, ISFLAG_KNOW_CURSE)) success = true; - set_ident_flags( you.inv[loopy], ISFLAG_KNOW_CURSE ); + set_ident_flags(item, ISFLAG_KNOW_CURSE); } } @@ -288,19 +285,18 @@ bool cast_bone_shards(int power, bolt &beam) { bool success = false; - if (you.equip[EQ_WEAPON] == -1 - || you.inv[you.equip[EQ_WEAPON]].base_type != OBJ_CORPSES) + if (!you.weapon() || you.weapon()->base_type != OBJ_CORPSES) { canned_msg(MSG_SPELL_FIZZLES); } - else if (you.inv[you.equip[EQ_WEAPON]].sub_type != CORPSE_SKELETON) + else if (you.weapon()->sub_type != CORPSE_SKELETON) mpr("The corpse collapses into a mass of pulpy flesh."); else { // Practical max of 100 * 15 + 3000 = 4500. // Actual max of 200 * 15 + 3000 = 6000. power *= 15; - power += mons_weight( you.inv[you.equip[EQ_WEAPON]].plus ); + power += mons_weight( you.weapon()->plus ); if (!player_tracer(ZAP_BONE_SHARDS, power, beam)) return (false); diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index 70856ff07b..82a451f88e 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -340,18 +340,17 @@ int spell_fail(spell_type spell) chance += armour; } - if (you.equip[EQ_WEAPON] != -1 - && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS) + if (you.weapon() && you.weapon()->base_type == OBJ_WEAPONS) { - int wpn_penalty = (3 * (property( you.inv[you.equip[EQ_WEAPON]], PWPN_SPEED ) - 12)) / 2; + int wpn_penalty = (3 * (property(*you.weapon(), PWPN_SPEED) - 12))/2; if (wpn_penalty > 0) chance += wpn_penalty; } - if (you.equip[EQ_SHIELD] != -1) + if (you.shield()) { - switch (you.inv[you.equip[EQ_SHIELD]].sub_type) + switch (you.shield()->sub_type) { case ARM_BUCKLER: chance += 5; @@ -764,9 +763,8 @@ bool maybe_identify_staff(item_def &item, spell_type spell) if (id_staff) { - item_def& wpn = you.inv[you.equip[EQ_WEAPON]]; - // changed from ISFLAG_KNOW_TYPE - set_ident_type( wpn, ID_KNOWN_TYPE ); + item_def& wpn = *you.weapon(); + set_ident_type(wpn, ID_KNOWN_TYPE); set_ident_flags( wpn, ISFLAG_IDENT_MASK); mprf("You are wielding %s.", wpn.name(DESC_NOCAP_A).c_str()); more(); @@ -778,11 +776,8 @@ bool maybe_identify_staff(item_def &item, spell_type spell) static void _spellcasting_side_effects(spell_type spell, bool idonly = false) { - if (you.equip[EQ_WEAPON] != -1 - && item_is_staff( you.inv[you.equip[EQ_WEAPON]] )) - { - maybe_identify_staff(you.inv[you.equip[EQ_WEAPON]], spell); - } + if (you.weapon() && item_is_staff(*you.weapon())) + maybe_identify_staff(*you.weapon(), spell); if (idonly) return; diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index 59fb01cfd7..6283c59aa5 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -857,12 +857,12 @@ static int damage_or_escape_net(int hold) int damage = -escape; // your weapon may damage the net, max. bonus of 2 - if (you.equip[EQ_WEAPON] != -1) + if (you.weapon()) { - if (can_cut_meat(you.inv[you.equip[EQ_WEAPON]])) + if (can_cut_meat(*you.weapon())) damage++; - - int brand = get_weapon_brand( you.inv[you.equip[EQ_WEAPON]] ); + + int brand = get_weapon_brand(*you.weapon()); if (brand == SPWPN_FLAMING || brand == SPWPN_VORPAL) damage++; } @@ -947,9 +947,9 @@ void free_self_from_net() { // For previously undamaged nets this takes at least 2 and at most // 8 turns. - bool can_slice = you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS - || you.equip[EQ_WEAPON] != -1 - && can_cut_meat(you.inv[you.equip[EQ_WEAPON]]); + bool can_slice = + (you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS) + || (you.weapon() && can_cut_meat(*you.weapon())); int damage = -do_what; diff --git a/crawl-ref/source/tutorial.cc b/crawl-ref/source/tutorial.cc index 8c9a99f57a..bdbda0c402 100644 --- a/crawl-ref/source/tutorial.cc +++ b/crawl-ref/source/tutorial.cc @@ -1261,9 +1261,9 @@ void tutorial_first_monster(const monsters &mon) "inventory, you'll find an explanation of how to do " "this. "; - if (you.equip[EQ_WEAPON] == -1 - || you.inv[you.equip[EQ_WEAPON]].base_type != OBJ_WEAPONS - || you.inv[you.equip[EQ_WEAPON]].sub_type != WPN_BOW) + if (!you.weapon() + || you.weapon()->base_type != OBJ_WEAPONS + || you.weapon()->sub_type != WPN_BOW) { text += "First wield it, then follow the instructions."; -- cgit v1.2.3-54-g00ecf