summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/mstuff2.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/mstuff2.cc')
-rw-r--r--crawl-ref/source/mstuff2.cc562
1 files changed, 386 insertions, 176 deletions
diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc
index 38d0d8c885..c47363ad7d 100644
--- a/crawl-ref/source/mstuff2.cc
+++ b/crawl-ref/source/mstuff2.cc
@@ -3,6 +3,8 @@
* Summary: Misc monster related functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <5> 31 July 2000 JDJ Fixed mon_throw to use lnchType.
@@ -26,7 +28,9 @@
#include "beam.h"
#include "debug.h"
#include "effects.h"
+#include "item_use.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
#include "misc.h"
#include "monplace.h"
@@ -38,7 +42,6 @@
#include "spl-cast.h"
#include "stuff.h"
#include "view.h"
-#include "wpn-misc.h"
static unsigned char monster_abjuration(int pow, bool test);
@@ -49,6 +52,9 @@ static unsigned char monster_abjuration(int pow, bool test);
// to be some sort of trap prior to function call: {dlb}
void mons_trap(struct monsters *monster)
{
+ if (!is_trap_square(monster->x, monster->y))
+ return;
+
int temp_rand = 0; // probability determination {dlb}
// single calculation permissible {dlb}
@@ -90,42 +96,42 @@ void mons_trap(struct monsters *monster)
{
case TRAP_DART:
projectileFired = true;
- strcpy(beem.beam_name, " dart");
+ beem.name = " dart";
beem.damage = dice_def( 1, 4 );
beem.colour = OBJ_MISSILES;
beem.type = MI_DART;
break;
case TRAP_NEEDLE:
projectileFired = true;
- strcpy(beem.beam_name, " needle");
+ beem.name = " needle";
beem.damage = dice_def( 1, 0 );
beem.colour = OBJ_MISSILES;
beem.type = MI_NEEDLE;
break;
case TRAP_ARROW:
projectileFired = true;
- strcpy(beem.beam_name, "n arrow");
+ beem.name = "n arrow";
beem.damage = dice_def( 1, 7 );
beem.colour = OBJ_MISSILES;
beem.type = MI_ARROW;
break;
case TRAP_SPEAR:
projectileFired = true;
- strcpy(beem.beam_name, " spear");
+ beem.name = " spear";
beem.damage = dice_def( 1, 10 );
beem.colour = OBJ_WEAPONS;
beem.type = WPN_SPEAR;
break;
case TRAP_BOLT:
projectileFired = true;
- strcpy(beem.beam_name, " bolt");
+ beem.name = " bolt";
beem.damage = dice_def( 1, 13 );
beem.colour = OBJ_MISSILES;
beem.type = MI_BOLT;
break;
case TRAP_AXE:
projectileFired = true;
- strcpy(beem.beam_name, "n axe");
+ beem.name = "n axe";
beem.damage = dice_def( 1, 15 );
beem.colour = OBJ_WEAPONS;
beem.type = WPN_HAND_AXE;
@@ -229,7 +235,7 @@ void mons_trap(struct monsters *monster)
temp_rand = random2(16);
beem.thrower = KILL_MON; // probably unnecessary
- beem.aux_source = NULL;
+ beem.aux_source.clear();
if (mons_friendly(monster))
{
@@ -282,13 +288,11 @@ void mons_trap(struct monsters *monster)
if (monsterNearby)
{
- snprintf( info, INFO_SIZE, "A%s %s %s%s!",
- beem.beam_name,
+ mprf("A%s %s %s%s!",
+ beem.name.c_str(),
(damage_taken >= 0) ? "hits" : "misses",
ptr_monam( monster, DESC_NOCAP_THE ),
- (damage_taken == 0) ? ", but does no damage" : "" );
-
- mpr(info);
+ (damage_taken == 0) ? ", but does no damage" : "");
}
if (apply_poison)
@@ -362,8 +366,12 @@ void mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cast)
switch (spell_cast)
{
+ case MS_SUMMON_SMALL_MAMMALS:
case MS_VAMPIRE_SUMMON:
- sumcount2 = 3 + random2(3) + monster->hit_dice / 5;
+ if ( spell_cast == MS_SUMMON_SMALL_MAMMALS )
+ sumcount2 = 1 + random2(4);
+ else
+ sumcount2 = 3 + random2(3) + monster->hit_dice / 5;
for (sumcount = 0; sumcount < sumcount2; sumcount++)
{
@@ -486,6 +494,28 @@ void mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cast)
monster->x, monster->y, monster->foe, 250 );
return;
+ case MS_SUMMON_MUSHROOMS: // Summon swarms of icky crawling fungi.
+ if (!mons_friendly(monster) && monsterNearby
+ && monster_abjuration(1, true) > 0 && coinflip())
+ {
+ monster_abjuration( monster->hit_dice * 10, false );
+ return;
+ }
+
+ sumcount2 = 1 + random2(2) + random2( monster->hit_dice / 4 + 1 );
+
+ duration = ENCH_ABJ_II + monster->hit_dice / 5;
+ if (duration > ENCH_ABJ_VI)
+ duration = ENCH_ABJ_VI;
+
+ for (int i = 0; i < sumcount2; ++i)
+ create_monster(MONS_WANDERING_MUSHROOM, duration,
+ SAME_ATTITUDE(monster),
+ monster->x, monster->y,
+ monster->foe,
+ 250);
+ return;
+
case MS_SUMMON_UNDEAD: // summon undead around player
if (!mons_friendly(monster) && monsterNearby
&& monster_abjuration(1, true) > 0 && coinflip())
@@ -506,7 +536,7 @@ void mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cast)
{
summonik = random2(241); // hmmmm ... {dlb}
}
- while (mons_holiness(summonik) != MH_UNDEAD);
+ while (mons_class_holiness(summonik) != MH_UNDEAD);
create_monster(summonik, duration, SAME_ATTITUDE(monster),
you.x_pos, you.y_pos, monster->foe, 250);
@@ -519,7 +549,7 @@ void mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cast)
simple_monster_message(monster, " calls on the powers of Hell!");
- torment(monster->x, monster->y);
+ torment(monster_index(monster), monster->x, monster->y);
return;
case MS_SUMMON_DEMON_GREATER:
@@ -544,6 +574,29 @@ void mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cast)
}
return;
+ // Journey -- Added in Summon Lizards and Draconian
+ case MS_SUMMON_LIZARDS:
+ if (!mons_friendly( monster ) && !monsterNearby &&
+ monster_abjuration( 1, true ) > 0 && coinflip())
+ {
+ monster_abjuration( monster->hit_dice * 10, false );
+ return;
+ }
+
+ sumcount2 = 1 + random2(3) + random2( monster->hit_dice / 5 + 1 );
+
+ duration = ENCH_ABJ_II + monster->hit_dice / 10;
+ if (duration > ENCH_ABJ_VI)
+ duration = ENCH_ABJ_VI;
+
+ for (sumcount = 0; sumcount < sumcount2; sumcount++)
+ {
+ create_monster( rand_dragon( DRAGON_LIZARD ), duration,
+ SAME_ATTITUDE(monster),
+ monster->x, monster->y, monster->foe, 250 );
+ }
+ break;
+
case MS_CANTRIP:
// Monster spell of uselessness, just prints a message.
// This spell exists so that some monsters with really strong
@@ -633,6 +686,7 @@ void setup_mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cas
// fire_tracer, or beam.
switch (spell_cast)
{
+ case MS_SUMMON_SMALL_MAMMALS:
case MS_VAMPIRE_SUMMON:
case MS_LEVEL_SUMMON: // summon anything appropriate for level
case MS_FAKE_RAKSHASA_SUMMON:
@@ -642,6 +696,8 @@ void setup_mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cas
case MS_SUMMON_UFETUBUS:
case MS_SUMMON_BEAST: // Geryon
case MS_SUMMON_UNDEAD: // summon undead around player
+ case MS_SUMMON_MUSHROOMS:
+ case MS_SUMMON_LIZARDS:
case MS_TORMENT:
case MS_SUMMON_DEMON_GREATER:
case MS_CANTRIP:
@@ -653,7 +709,7 @@ void setup_mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cas
// Need to correct this for power of spellcaster
int power = 12 * monster->hit_dice;
- struct SBeam theBeam = mons_spells(spell_cast, power);
+ struct bolt theBeam = mons_spells(spell_cast, power);
pbolt.colour = theBeam.colour;
pbolt.range = theBeam.range;
@@ -663,18 +719,19 @@ void setup_mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cas
pbolt.ench_power = theBeam.ench_power;
pbolt.type = theBeam.type;
pbolt.flavour = theBeam.flavour;
- pbolt.thrower = theBeam.thrown;
- pbolt.aux_source = NULL;
- strcpy( pbolt.beam_name, theBeam.name.c_str() );
- pbolt.isBeam = theBeam.isBeam;
+ pbolt.thrower = theBeam.thrower;
+ pbolt.aux_source.clear();
+ pbolt.name = theBeam.name;
+ pbolt.is_beam = theBeam.is_beam;
pbolt.source_x = monster->x;
pbolt.source_y = monster->y;
- pbolt.isTracer = false;
+ pbolt.is_tracer = false;
+ pbolt.is_explosion = theBeam.is_explosion;
- if (pbolt.beam_name[0] && pbolt.beam_name[0] != '0')
- pbolt.aux_source = pbolt.beam_name;
+ if (pbolt.name.length() && pbolt.name[0] != '0')
+ pbolt.aux_source = pbolt.name;
else
- pbolt.aux_source = NULL;
+ pbolt.aux_source.clear();
if (spell_cast == MS_HASTE
|| spell_cast == MS_INVIS
@@ -683,16 +740,25 @@ void setup_mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cas
pbolt.target_x = monster->x;
pbolt.target_y = monster->y;
}
+
+ // Convenience for the hapless innocent who assumes that this
+ // damn function does all possible setup. [ds]
+ if (!pbolt.target_x && !pbolt.target_y)
+ {
+ pbolt.target_x = monster->target_x;
+ pbolt.target_y = monster->target_y;
+ }
} // end setup_mons_cast()
-void monster_teleport(struct monsters *monster, bool instan)
+void monster_teleport(struct monsters *monster, bool instan, bool silent)
{
if (!instan)
{
if (mons_del_ench(monster, ENCH_TP_I, ENCH_TP_IV))
{
- simple_monster_message(monster, " seems more stable.");
+ if (!silent)
+ simple_monster_message(monster, " seems more stable.");
}
else
mons_add_ench(monster, (coinflip() ? ENCH_TP_III : ENCH_TP_IV ));
@@ -700,13 +766,14 @@ void monster_teleport(struct monsters *monster, bool instan)
return;
}
- simple_monster_message(monster, " disappears!");
+ bool was_seen = player_monster_visible(monster) && mons_near(monster);
+
+ if (!silent)
+ simple_monster_message(monster, " disappears!");
// pick the monster up
mgrd[monster->x][monster->y] = NON_MONSTER;
- char ogrid = monster_habitat(monster->type);
-
int newx, newy;
while(true)
{
@@ -717,12 +784,7 @@ void monster_teleport(struct monsters *monster, bool instan)
if (mgrd[newx][newy] != NON_MONSTER)
continue;
- // monsters going to the same habitat
- if (ogrid == grd[newx][newy])
- break;
-
- // DEEP_WATER monsters can be teleported to SHALLOW_WATER
- if (ogrid == DNGN_DEEP_WATER && grd[newx][newy] == DNGN_SHALLOW_WATER)
+ if (monster_habitable_grid(monster, grd[newx][newy]))
break;
}
@@ -735,46 +797,85 @@ void monster_teleport(struct monsters *monster, bool instan)
if (mons_is_mimic( monster->type ))
{
monster->type = MONS_GOLD_MIMIC + random2(5);
- monster->number = get_mimic_colour( monster );
+ monster->colour = get_mimic_colour( monster );
+ }
+
+ if (!silent)
+ {
+ if (was_seen)
+ simple_monster_message(monster, " reappears nearby!");
+ else
+ simple_monster_message(monster, " appears out of thin air!");
}
+
+ if (player_monster_visible(monster) && mons_near(monster))
+ seen_monster(monster);
} // end monster_teleport()
void setup_dragon(struct monsters *monster, struct bolt &pbolt)
{
- strcpy(pbolt.beam_name, ptr_monam( monster, DESC_PLAIN ));
+ const int type = (mons_genus( monster->type ) == MONS_DRACONIAN)
+ ? draco_subspecies( monster ) : monster->type;
+ int scaling = 100;
+
+ pbolt.name = ptr_monam( monster, DESC_PLAIN );
- switch (monster->type)
+ switch (type)
{
case MONS_FIREDRAKE:
case MONS_HELL_HOUND:
case MONS_DRAGON:
case MONS_LINDWURM:
case MONS_XTAHUA:
- strcat(pbolt.beam_name, "'s blast of flame");
+ pbolt.name += "'s blast of flame";
pbolt.flavour = BEAM_FIRE;
pbolt.colour = RED;
- pbolt.aux_source = "blast of flame";
+ pbolt.aux_source = "blast of fiery breath";
break;
case MONS_ICE_DRAGON:
- strcat(pbolt.beam_name, "'s blast of cold");
+ pbolt.name += "'s blast of cold";
pbolt.flavour = BEAM_COLD;
pbolt.colour = WHITE;
- pbolt.aux_source = "blast of cold";
+ pbolt.aux_source = "blast of icy breath";
+ break;
+
+ case MONS_RED_DRACONIAN:
+ pbolt.name += "'s searing breath";
+#ifdef DEBUG_DIAGNOSTICS
+ mprf( MSGCH_DIAGNOSTICS, "bolt name: '%s'", pbolt.name.c_str() );
+#endif
+ pbolt.flavour = BEAM_FIRE;
+ pbolt.colour = RED;
+ pbolt.aux_source = "blast of searing breath";
+ scaling = 65;
break;
+ case MONS_WHITE_DRACONIAN:
+ pbolt.name += "'s chilling breath";
+#ifdef DEBUG_DIAGNOSTICS
+ mprf( MSGCH_DIAGNOSTICS, "bolt name: '%s'", pbolt.name.c_str() );
+#endif
+ pbolt.flavour = BEAM_COLD;
+ pbolt.colour = WHITE;
+ pbolt.aux_source = "blast of chilling breath";
+ scaling = 65;
+ break;
+
default:
DEBUGSTR("Bad monster class in setup_dragon()");
+ break;
}
pbolt.range = 4;
pbolt.rangeMax = 13;
pbolt.damage = dice_def( 3, (monster->hit_dice * 2) );
+ pbolt.damage.size = scaling * pbolt.damage.size / 100;
pbolt.type = SYM_ZAP;
pbolt.hit = 30;
pbolt.beam_source = monster_index(monster);
pbolt.thrower = KILL_MON;
- pbolt.isBeam = true;
+ pbolt.is_beam = true;
} // end setup_dragon();
void setup_generic_throw(struct monsters *monster, struct bolt &pbolt)
@@ -786,19 +887,20 @@ void setup_generic_throw(struct monsters *monster, struct bolt &pbolt)
pbolt.type = SYM_MISSILE;
pbolt.flavour = BEAM_MISSILE;
pbolt.thrower = KILL_MON_MISSILE;
- pbolt.aux_source = NULL;
- pbolt.isBeam = false;
+ pbolt.aux_source.clear();
+ pbolt.is_beam = false;
}
// decide if something is launched or thrown
-// pass -1 for launcher class & 0 for type if no weapon is weilded
+// pass -1 for launcher class & 0 for type if no weapon is wielded
void throw_type( int lnchClass, int lnchType, int wepClass, int wepType,
bool &launched, bool &thrown )
{
if (wepClass == OBJ_MISSILES
&& lnchClass == OBJ_WEAPONS
- && launches_things(lnchType) && wepType == launched_by(lnchType))
+ && is_range_weapon_type((weapon_type) lnchType)
+ && wepType == fires_ammo_type((weapon_type) lnchType))
{
launched = true;
}
@@ -836,9 +938,11 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
int ammoHitBonus = 0, ammoDamBonus = 0; // from thrown or ammo
int lnchHitBonus = 0, lnchDamBonus = 0; // special add from launcher
int exHitBonus = 0, exDamBonus = 0; // 'extra' bonus from skill/dex/str
+ int lnchBaseDam = 0;
int hitMult = 0;
int damMult = 0;
+ int diceMult = 100;
bool launched = false; // item is launched
bool thrown = false; // item is sensible thrown item
@@ -862,7 +966,7 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
pbolt.colour = item.colour;
pbolt.flavour = BEAM_MISSILE;
pbolt.thrower = KILL_MON_MISSILE;
- pbolt.aux_source = NULL;
+ pbolt.aux_source.clear();
// figure out if we're thrown or launched
throw_type( lnchClass, lnchType, wepClass, wepType, launched, thrown );
@@ -872,6 +976,7 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
{
lnchHitBonus = mitm[ weapon ].plus;
lnchDamBonus = mitm[ weapon ].plus2;
+ lnchBaseDam = property(mitm[weapon], PWPN_DAMAGE);
}
// extract weapon/ammo bonuses due to magic
@@ -897,9 +1002,14 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
baseDam = property( item, PWPN_DAMAGE );
if (wepClass == OBJ_MISSILES) // throw missile
+ {
// ammo damage needs adjusting here - OBJ_MISSILES
// don't get separate tohit/damage bonuses!
ammoDamBonus = ammoHitBonus;
+ // [dshaligram] Thrown stones/darts do only half the damage of
+ // launched stones/darts. This matches 4.0 behaviour.
+ baseDam = div_rand_round(baseDam, 2);
+ }
// give monster "skill" bonuses based on HD
exHitBonus = (hitMult * monster->hit_dice) / 10 + 1;
@@ -917,6 +1027,7 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
lnchDamBonus = 0;
break;
case WPN_BOW:
+ case WPN_LONGBOW:
baseHit = 0;
hitMult = 60;
damMult = 35;
@@ -944,7 +1055,10 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
break;
}
- baseDam = property( item, PWPN_HIT );
+ // Launcher is now more important than ammo for base damage.
+ baseDam = property(item, PWPN_DAMAGE);
+ if (lnchBaseDam)
+ baseDam = lnchBaseDam + random2(1 + baseDam);
// missiles don't have pluses2; use hit bonus
ammoDamBonus = ammoHitBonus;
@@ -952,6 +1066,21 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
exHitBonus = (hitMult * monster->hit_dice) / 10 + 1;
exDamBonus = (damMult * monster->hit_dice) / 10 + 1;
+ // monsters no longer gain unfair advantages with weapons of fire/ice
+ // and incorrect ammo. They now have same restriction as players.
+
+ const int bow_brand =
+ get_weapon_brand(mitm[monster->inv[MSLOT_WEAPON]]);
+ const int ammo_brand = get_ammo_brand( item );
+
+ if (!baseDam && elemental_missile_beam(bow_brand, ammo_brand))
+ baseDam = 4;
+
+ // [dshaligram] This is a horrible hack - we force beam.cc to consider
+ // this beam "needle-like".
+ if (wepClass == OBJ_MISSILES && wepType == MI_NEEDLE)
+ pbolt.ench_power = AUTOMATIC_HIT;
+
// elven bow w/ elven arrow, also orcish
if (get_equip_race( mitm[monster->inv[MSLOT_WEAPON]] )
== get_equip_race( mitm[monster->inv[MSLOT_MISSILE]] ))
@@ -959,17 +1088,10 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
baseHit++;
baseDam++;
- if (cmp_equip_race(mitm[monster->inv[MSLOT_WEAPON]], ISFLAG_ELVEN))
+ if (get_equip_race(mitm[monster->inv[MSLOT_WEAPON]]) == ISFLAG_ELVEN)
pbolt.hit++;
}
- // monsters no longer gain unfair advantages with weapons of fire/ice
- // and incorrect ammo. They now have same restriction as players.
-
- const int bow_brand = get_weapon_brand(mitm[monster->inv[MSLOT_WEAPON]]);
-
- const int ammo_brand = get_ammo_brand( item );
-
bool poison = (ammo_brand == SPMSL_POISONED
|| ammo_brand == SPMSL_POISONED_II);
@@ -977,6 +1099,9 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
if (bow_brand == SPWPN_VENOM && ammo_brand == SPMSL_NORMAL)
set_item_ego_type( item, OBJ_MISSILES, SPMSL_POISONED );
+ // Vorpal brand increases damage dice size.
+ if (bow_brand == SPWPN_VORPAL)
+ diceMult = diceMult * 130 / 100;
// WEAPON or AMMO of FIRE
if ((bow_brand == SPWPN_FLAME || ammo_brand == SPMSL_FLAME)
@@ -984,13 +1109,14 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
{
baseHit += 2;
exDamBonus += 6;
+
pbolt.flavour = BEAM_FIRE;
- strcpy(pbolt.beam_name, "bolt of ");
+ pbolt.name = "bolt of ";
if (poison)
- strcat(pbolt.beam_name, "poison ");
+ pbolt.name += "poison ";
- strcat(pbolt.beam_name, "flame");
+ pbolt.name += "flame";
pbolt.colour = RED;
pbolt.type = SYM_ZAP;
}
@@ -1001,13 +1127,14 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
{
baseHit += 2;
exDamBonus += 6;
+
pbolt.flavour = BEAM_COLD;
- strcpy(pbolt.beam_name, "bolt of ");
+ pbolt.name = "bolt of ";
if (poison)
- strcat(pbolt.beam_name, "poison ");
+ pbolt.name += "poison ";
- strcat(pbolt.beam_name, "frost");
+ pbolt.name += "frost";
pbolt.colour = WHITE;
pbolt.type = SYM_ZAP;
}
@@ -1023,16 +1150,16 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
if (mons_intel(monster->type) == I_HIGH)
exHitBonus += 10;
- // now, if a monster is, for some reason, throwing something really
- // stupid, it will have baseHit of 0 and damage of 0. Ah well.
+ // now, if a monster is, for some reason, throwing something really
+ // stupid, it will have baseHit of 0 and damage of 0. Ah well.
strcpy(info, ptr_monam( monster, DESC_CAP_THE) );
strcat(info, (launched) ? " shoots " : " throws ");
- if (strlen(pbolt.beam_name) > 0)
+ if (pbolt.name.length())
{
strcat(info, "a ");
- strcat(info, pbolt.beam_name);
+ strcat(info, pbolt.name.c_str());
}
else
{
@@ -1043,23 +1170,24 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
// build beam name
item_name( item, DESC_PLAIN, str_pass );
- strcpy(pbolt.beam_name, str_pass);
+ pbolt.name = str_pass;
}
strcat(info, ".");
mpr(info);
-
+ // [dshaligram] When changing bolt names here, you must edit
+ // hiscores.cc (scorefile_entry::terse_missile_cause()) to match.
if (launched)
{
snprintf( throw_buff, sizeof(throw_buff), "Shot with a%s %s by %s",
- (is_vowel(pbolt.beam_name[0]) ? "n" : ""), pbolt.beam_name,
+ (is_vowel(pbolt.name[0]) ? "n" : ""), pbolt.name.c_str(),
ptr_monam( monster, DESC_NOCAP_A ) );
}
else
{
snprintf( throw_buff, sizeof(throw_buff), "Hit by a%s %s thrown by %s",
- (is_vowel(pbolt.beam_name[0]) ? "n" : ""), pbolt.beam_name,
+ (is_vowel(pbolt.name[0]) ? "n" : ""), pbolt.name.c_str(),
ptr_monam( monster, DESC_NOCAP_A ) );
}
@@ -1075,6 +1203,9 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
pbolt.hit += lnchHitBonus;
}
+ pbolt.damage.size = diceMult * pbolt.damage.size / 100;
+ scale_dice(pbolt.damage);
+
// decrease inventory
fire_beam( pbolt, &item );
@@ -1094,18 +1225,19 @@ void spore_goes_pop(struct monsters *monster)
if (monster == NULL)
return;
- beam.isTracer = false;
+ beam.is_tracer = false;
+ beam.is_explosion = true;
beam.beam_source = monster_index(monster);
beam.type = SYM_BURST;
beam.target_x = monster->x;
beam.target_y = monster->y;
beam.thrower = KILL_MON; // someone else's explosion
- beam.aux_source = NULL;
+ beam.aux_source.clear();
if (type == MONS_GIANT_SPORE)
{
beam.flavour = BEAM_SPORE;
- strcpy(beam.beam_name, "explosion of spores");
+ beam.name = "explosion of spores";
beam.colour = LIGHTGREY;
beam.damage = dice_def( 3, 15 );
beam.ex_size = 2;
@@ -1114,7 +1246,7 @@ void spore_goes_pop(struct monsters *monster)
else
{
beam.flavour = BEAM_ELECTRICITY;
- strcpy(beam.beam_name, "blast of lightning");
+ beam.name = "blast of lightning";
beam.colour = LIGHTCYAN;
beam.damage = dice_def( 3, 20 );
beam.ex_size = coinflip() ? 3 : 2;
@@ -1130,21 +1262,23 @@ void spore_goes_pop(struct monsters *monster)
explosion(beam);
} // end spore_goes_pop()
-struct SBeam mons_spells( int spell_cast, int power )
+bolt mons_spells( int spell_cast, int power )
{
ASSERT(power > 0);
- struct SBeam beam;
+ bolt beam;
beam.name = "****"; // initialize to some bogus values so we can catch problems
beam.colour = 1000;
- beam.range = -1;
+ beam.range = beam.rangeMax = 8;
beam.hit = -1;
beam.damage = dice_def( 1, 0 );
beam.ench_power = -1;
beam.type = -1;
beam.flavour = -1;
- beam.thrown = -1;
+ beam.thrower = -1;
+ beam.is_beam = false;
+ beam.is_explosion = false;
switch (spell_cast)
{
@@ -1156,9 +1290,9 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 4 + (power / 100) );
beam.hit = 1500;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_MMISSILE;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_FLAME:
@@ -1174,9 +1308,9 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.hit = 60;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_FIRE;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_FROST:
@@ -1191,9 +1325,9 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.hit = 60;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_COLD;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_PARALYSIS:
@@ -1202,8 +1336,8 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_PARALYSIS;
- beam.thrown = KILL_MON_MISSILE;
- beam.isBeam = true;
+ beam.thrower = KILL_MON_MISSILE;
+ beam.is_beam = true;
break;
case MS_SLOW:
@@ -1212,8 +1346,8 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_SLOW;
- beam.thrown = KILL_MON_MISSILE;
- beam.isBeam = true;
+ beam.thrower = KILL_MON_MISSILE;
+ beam.is_beam = true;
break;
case MS_HASTE: // (self)
@@ -1222,8 +1356,8 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_HASTE;
- beam.thrown = KILL_MON_MISSILE;
- beam.isBeam = true;
+ beam.thrower = KILL_MON_MISSILE;
+ beam.is_beam = true;
break;
case MS_CONFUSE:
@@ -1232,8 +1366,8 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_CONFUSION;
- beam.thrown = KILL_MON_MISSILE;
- beam.isBeam = true;
+ beam.thrower = KILL_MON_MISSILE;
+ beam.is_beam = true;
break;
case MS_VENOM_BOLT:
@@ -1243,10 +1377,21 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 6 + power / 13 );
beam.colour = LIGHTGREEN;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_POISON;
- beam.hit = 7 + random2(power) / 80;
- beam.isBeam = true;
+ beam.hit = 8 + power / 20;
+ beam.is_beam = true;
+ break;
+
+ case MS_POISON_ARROW:
+ beam.name = "poison arrow";
+ beam.damage = dice_def( 4, 5 + power / 12 );
+ beam.colour = LIGHTGREEN;
+ beam.type = SYM_MISSILE;
+ beam.thrower = KILL_MON;
+ beam.flavour = BEAM_POISON_ARROW;
+ beam.hit = 14 + power / 25;
+ beam.range = beam.rangeMax = 8;
break;
case MS_FIRE_BOLT:
@@ -1256,10 +1401,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 8 + power / 11 );
beam.colour = RED;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_FIRE;
- beam.hit = 8 + random2(power) / 80; // hit
- beam.isBeam = true;
+ beam.hit = 12 + power / 25;
+ beam.is_beam = true;
break;
case MS_COLD_BOLT:
@@ -1269,10 +1414,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 8 + power / 11 );
beam.colour = WHITE;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_COLD;
- beam.hit = 8 + random2(power) / 80; // hit
- beam.isBeam = true;
+ beam.hit = 12 + power / 25;
+ beam.is_beam = true;
break;
case MS_LIGHTNING_BOLT:
@@ -1282,10 +1427,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 10 + power / 9 );
beam.colour = LIGHTCYAN;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_ELECTRICITY;
- beam.hit = 10 + random2(power) / 40;
- beam.isBeam = true;
+ beam.hit = 10 + power / 40;
+ beam.is_beam = true;
break;
case MS_INVIS:
@@ -1294,8 +1439,8 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_INVISIBILITY;
- beam.thrown = KILL_MON;
- beam.isBeam = true;
+ beam.thrower = KILL_MON;
+ beam.is_beam = true;
break;
case MS_FIREBALL:
@@ -1306,9 +1451,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 7 + power / 10 );
beam.hit = 40;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
- beam.flavour = BEAM_EXPLOSION; // why not BEAM_FIRE? {dlb}
- beam.isBeam = false;
+ beam.thrower = KILL_MON;
+ beam.flavour = BEAM_FIRE; // why not BEAM_FIRE? {dlb}
+ beam.is_beam = false;
+ beam.is_explosion = true;
break;
case MS_HEAL:
@@ -1317,9 +1463,9 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_HEALING;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.hit = 5 + (power / 5);
- beam.isBeam = true;
+ beam.is_beam = true;
break;
case MS_TELEPORT:
@@ -1328,8 +1474,8 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_TELEPORT; // 6 is used by digging
- beam.thrown = KILL_MON;
- beam.isBeam = true;
+ beam.thrower = KILL_MON;
+ beam.is_beam = true;
break;
case MS_TELEPORT_OTHER:
@@ -1338,12 +1484,12 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_TELEPORT; // 6 is used by digging
- beam.thrown = KILL_MON;
- beam.isBeam = true;
+ beam.thrower = KILL_MON;
+ beam.is_beam = true;
break;
case MS_BLINK:
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_CRYSTAL_SPEAR: // was splinters
@@ -1353,10 +1499,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 12 + power / 10 );
beam.colour = WHITE;
beam.type = SYM_MISSILE;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_MMISSILE;
- beam.hit = 6; // + random2(power) / 10;
- beam.isBeam = false;
+ beam.hit = 14 + power / 20;
+ beam.is_beam = false;
break;
case MS_DIG:
@@ -1365,8 +1511,8 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 7 + random2(power) / 10;
beam.type = 0;
beam.flavour = BEAM_DIGGING;
- beam.thrown = KILL_MON;
- beam.isBeam = true;
+ beam.thrower = KILL_MON;
+ beam.is_beam = true;
break;
case MS_NEGATIVE_BOLT: // negative energy
@@ -1376,10 +1522,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 6 + power / 13 );
beam.colour = DARKGREY;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_NEG;
- beam.hit = 7 + random2(power) / 80;
- beam.isBeam = true;
+ beam.hit = 11 + power / 35;
+ beam.is_beam = true;
break;
// 20, 21 are used
@@ -1390,11 +1536,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.range = 6;
beam.rangeMax = 10;
beam.damage = dice_def( 3, 7 + (power / 14) );
- beam.hit = 10 + (power / 20);
+ beam.hit = 12 + (power / 20);
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_MMISSILE;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
// 23 is brain feed
@@ -1404,12 +1550,12 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.name = "ball of steam";
beam.range = 6;
beam.rangeMax = 10;
- beam.damage = dice_def( 3, 6 );
- beam.hit = 11;
+ beam.damage = dice_def( 3, 7 + (power / 15) );
+ beam.hit = 11 + power / 20;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
- beam.flavour = BEAM_FIRE; // fire - I think this is appropriate
- beam.isBeam = false;
+ beam.thrower = KILL_MON_MISSILE;
+ beam.flavour = BEAM_STEAM;
+ beam.is_beam = false;
break;
// 27 is summon devils
@@ -1421,11 +1567,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 14;
beam.type = 0;
beam.flavour = BEAM_PAIN; // pain
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
// beam.damage = dice_def( 1, 50 );
beam.damage = dice_def( 1, 7 + (power / 20) );
beam.ench_power = 50;
- beam.isBeam = true;
+ beam.is_beam = true;
break;
// 30 is smiting
@@ -1436,11 +1582,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.range = 6;
beam.rangeMax = 10;
beam.damage = dice_def( 3, 3 + power / 50 );
- beam.hit = 8 + power / 15;
+ beam.hit = 10 + power / 15;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_FIRE;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_POISON_BLAST: // demon
@@ -1450,10 +1596,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 3 + power / 25 );
beam.colour = LIGHTGREEN;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_POISON;
- beam.hit = 7 + random2(power) / 80;
- beam.isBeam = true;
+ beam.hit = 11 + power / 25;
+ beam.is_beam = true;
+ beam.is_big_cloud = true;
break;
case MS_PURPLE_BLAST: // purple bang thing
@@ -1462,11 +1609,12 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.range = 6;
beam.rangeMax = 10;
beam.damage = dice_def( 3, 10 + power / 15 );
- beam.hit = 10 + power / 20;
+ beam.hit = 11 + power / 25;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
- beam.flavour = BEAM_EXPLOSION; // an exploding magical missile
- beam.isBeam = false;
+ beam.thrower = KILL_MON_MISSILE;
+ beam.flavour = BEAM_MMISSILE;
+ beam.is_beam = false;
+ beam.is_explosion = true;
break;
case MS_ENERGY_BOLT: // eye of devastation
@@ -1475,11 +1623,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.range = 9;
beam.rangeMax = 23;
beam.damage = dice_def( 3, 20 );
- beam.hit = 9;
+ beam.hit = 11 + power / 30;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_NUKE; // a magical missile which destroys walls
- beam.isBeam = true;
+ beam.is_beam = true;
break;
case MS_STING: // sting
@@ -1490,9 +1638,9 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 1, 6 + power / 25 );
beam.hit = 60;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_POISON;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_IRON_BOLT:
@@ -1501,11 +1649,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.range = 4;
beam.rangeMax = 8;
beam.damage = dice_def( 3, 8 + (power / 9) );
- beam.hit = 6 + (power / 25);
+ beam.hit = 12 + (power / 25);
beam.type = SYM_MISSILE;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_MMISSILE; // similarly unresisted thing
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_STONE_ARROW:
@@ -1514,11 +1662,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.range = 8;
beam.rangeMax = 12;
beam.damage = dice_def( 3, 5 + (power / 10) );
- beam.hit = 5 + power / 47;
+ beam.hit = 8 + power / 35;
beam.type = SYM_MISSILE;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_MMISSILE; // similarly unresisted thing
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_POISON_SPLASH:
@@ -1527,11 +1675,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.range = 5;
beam.rangeMax = 10;
beam.damage = dice_def( 1, 4 + power / 10 );
- beam.hit = 9;
+ beam.hit = 9 + power / 20;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_POISON;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_DISINTEGRATE:
@@ -1540,11 +1688,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 14;
beam.type = 0;
beam.flavour = BEAM_DISINTEGRATION;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.ench_power = 50;
// beam.hit = 30 + (power / 10);
beam.damage = dice_def( 1, 30 + (power / 10) );
- beam.isBeam = true;
+ beam.is_beam = true;
break;
case MS_MARSH_GAS: // swamp drake
@@ -1554,23 +1702,37 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 2 + power / 25 );
beam.colour = GREEN;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_POISON;
- beam.hit = 7 + random2(power) / 80;
- beam.isBeam = false;
+ beam.hit = 12 + power / 30;
+ beam.is_beam = true;
+ beam.is_big_cloud = true;
break;
+ case MS_MIASMA: // death drake
+ beam.name = "foul vapour";
+ beam.damage = dice_def( 3, 5 + power / 24 );
+ beam.colour = DARKGREY;
+ beam.type = SYM_ZAP;
+ beam.thrower = KILL_MON;
+ beam.flavour = BEAM_MIASMA;
+ beam.hit = 12 + power / 20;
+ beam.is_beam = true;
+ beam.is_big_cloud = true;
+ beam.range = beam.rangeMax = 8;
+ break;
+
case MS_QUICKSILVER_BOLT: // Quicksilver dragon
beam.colour = random_colour();
beam.name = "bolt of energy";
beam.range = 9;
beam.rangeMax = 23;
beam.damage = dice_def( 3, 25 );
- beam.hit = 9;
+ beam.hit = 9 + power / 25;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_MMISSILE;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_HELLFIRE: // fiend's hellfire
@@ -1581,9 +1743,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 25 );
beam.hit = 20;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
- beam.flavour = BEAM_EXPLOSION; // hellfire - not BEAM_HELLFIRE? {dlb}
- beam.isBeam = true;
+ beam.thrower = KILL_MON;
+ beam.flavour = BEAM_HELLFIRE;
+ beam.is_beam = true;
+ beam.is_explosion = true;
break;
case MS_METAL_SPLINTERS:
@@ -1593,10 +1756,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 20 + power / 20 );
beam.colour = CYAN;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_FRAG;
- beam.hit = 15 + random2(power) / 50;
- beam.isBeam = true;
+ beam.hit = 15 + power / 30;
+ beam.is_beam = true;
break;
case MS_BANISHMENT:
@@ -1605,8 +1768,19 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_BANISH;
- beam.thrown = KILL_MON_MISSILE;
- beam.isBeam = true;
+ beam.thrower = KILL_MON_MISSILE;
+ beam.is_beam = true;
+ break;
+
+ case MS_BLINK_OTHER:
+ beam.name = "0";
+ beam.type = 0;
+ beam.flavour = BEAM_BLINK;
+ beam.thrower = KILL_MON;
+ beam.is_beam = true;
+ beam.is_enchant = true;
+ beam.range = 8;
+ beam.rangeMax = 8;
break;
default:
@@ -1663,3 +1837,39 @@ static unsigned char monster_abjuration(int pow, bool test)
return result;
} // end monster_abjuration()
+
+bool silver_statue_effects(monsters *mons)
+{
+ if ((mons_player_visible(mons) || one_chance_in(3))
+ && !one_chance_in(3))
+ {
+ char wc[30];
+
+ weird_colours( random2(256), wc );
+ snprintf(info, INFO_SIZE, "'s eyes glow %s.", wc);
+ simple_monster_message(mons, info, MSGCH_WARN);
+
+ create_monster( summon_any_demon((coinflip() ? DEMON_COMMON
+ : DEMON_LESSER)),
+ ENCH_ABJ_V, BEH_HOSTILE,
+ you.x_pos, you.y_pos,
+ MHITYOU, 250 );
+ return (true);
+ }
+ return (false);
+}
+
+bool orange_statue_effects(monsters *mons)
+{
+ if ((mons_player_visible(mons) || one_chance_in(3))
+ && !one_chance_in(3))
+ {
+ mpr("A hostile presence attacks your mind!", MSGCH_WARN);
+
+ miscast_effect( SPTYP_DIVINATION, random2(15), random2(150), 100,
+ "an orange crystal statue" );
+ return (true);
+ }
+
+ return (false);
+}