summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authordolorous <dolorous@c06c8d41-db1a-0410-9941-cceddc491573>2009-09-18 06:52:42 +0000
committerdolorous <dolorous@c06c8d41-db1a-0410-9941-cceddc491573>2009-09-18 06:52:42 +0000
commit9f751c796fa4ca1c22e66d4f31f293c0ea1955b6 (patch)
tree4d300ceda8beba72814a2de26bc723a911e67391 /crawl-ref/source
parenta06edf5979429958d25705d9ea9a93e8a97da45d (diff)
downloadcrawl-ref-9f751c796fa4ca1c22e66d4f31f293c0ea1955b6.tar.gz
crawl-ref-9f751c796fa4ca1c22e66d4f31f293c0ea1955b6.zip
Implement part of [2837033]: Randomize colors, resistances, and attack
types/flavors for ugly things. They now use the ghost_demon struct, expanded to account for these characteristics. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@10709 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/dat/descript/monsters.txt4
-rw-r--r--crawl-ref/source/debug.cc5
-rw-r--r--crawl-ref/source/describe.cc5
-rw-r--r--crawl-ref/source/externs.h3
-rw-r--r--crawl-ref/source/ghost.cc196
-rw-r--r--crawl-ref/source/ghost.h6
-rw-r--r--crawl-ref/source/mgrow.cc11
-rw-r--r--crawl-ref/source/mon-data.h12
-rw-r--r--crawl-ref/source/mon-util.cc35
-rw-r--r--crawl-ref/source/monplace.cc12
-rw-r--r--crawl-ref/source/stuff.cc16
-rw-r--r--crawl-ref/source/stuff.h2
-rw-r--r--crawl-ref/source/tags.cc13
-rw-r--r--crawl-ref/source/tags.h3
14 files changed, 301 insertions, 22 deletions
diff --git a/crawl-ref/source/dat/descript/monsters.txt b/crawl-ref/source/dat/descript/monsters.txt
index 75fa132592..0e288ad2c7 100644
--- a/crawl-ref/source/dat/descript/monsters.txt
+++ b/crawl-ref/source/dat/descript/monsters.txt
@@ -1416,7 +1416,7 @@ A chattering and shrieking minor demon.
%%%%
ugly thing
-An ugly thing. Yuck.
+An ugly thing. According to legend, this mutated creature is the spawn of an otherworldly wizard's breeding experiment. Yuck.
%%%%
unseen horror
@@ -1444,7 +1444,7 @@ A heavily armed and armoured guardian of the Vaults.
%%%%
very ugly thing
-A very ugly thing. Double yuck.
+A very ugly thing. According to legend, this hideously mutated creature is the spawn of an otherworldly wizard's breeding experiment. Double yuck.
%%%%
wandering mushroom
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index 44911b0945..0077837804 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -2722,8 +2722,9 @@ void debug_stethoscope(int mon)
{
ASSERT(mons.ghost.get());
const ghost_demon &ghost = *mons.ghost;
- mprf(MSGCH_DIAGNOSTICS, "Ghost damage: %d; brand: %d",
- ghost.damage, ghost.brand);
+ mprf(MSGCH_DIAGNOSTICS, "Ghost damage: %d; brand: %d; att_type: %d; "
+ "att_flav: %d",
+ ghost.damage, ghost.brand, ghost.att_type, ghost.att_flav);
}
}
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index c738b23d72..d5c8a27200 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -2705,8 +2705,9 @@ static std::string _monster_stat_description(const monsters& mon)
}
// Can the monster levitate/fly?
- // This doesn't give anything away since all ghosts can fly, and
- // for demons it's already mentioned in their flavour description.
+ // This doesn't give anything away since no (very) ugly things can
+ // fly, all ghosts can fly, and for demons it's already mentioned in
+ // their flavour description.
const flight_type fly = mons_flies(&mon, false);
if (fly != FL_NONE)
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 4b53327a4c..c310ce8d7c 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1361,9 +1361,10 @@ public:
bool find_home_around(const coord_def &c, int radius);
bool find_home_anywhere();
- void set_ghost(const ghost_demon &ghost);
+ void set_ghost(const ghost_demon &ghost, bool has_name = true);
void ghost_init();
void pandemon_init();
+ void uglything_init();
void destroy_inventory();
void load_spells(mon_spellbook_type spellbook);
diff --git a/crawl-ref/source/ghost.cc b/crawl-ref/source/ghost.cc
index 52fd438f26..8197b89c21 100644
--- a/crawl-ref/source/ghost.cc
+++ b/crawl-ref/source/ghost.cc
@@ -24,6 +24,7 @@ REVISION("$Rev$");
#include "place.h"
#include "player.h"
#include "religion.h"
+#include "view.h"
#include <vector>
#define MAX_GHOST_DAMAGE 50
@@ -138,9 +139,12 @@ void ghost_demon::reset()
speed = 10;
see_invis = false;
brand = SPWPN_NORMAL;
+ att_type = AT_HIT;
+ att_flav = AF_PLAIN;
resists = mon_resist_def();
spellcaster = false;
cycle_colours = false;
+ colour = BLACK;
fly = FL_NONE;
}
@@ -219,6 +223,8 @@ void ghost_demon::init_random_demon()
// Does demon cycle colours?
cycle_colours = one_chance_in(10);
+ colour = random_colour();
+
spells.init(SPELL_NO_SPELL);
// This bit uses the list of player spells to find appropriate
@@ -387,11 +393,201 @@ void ghost_demon::init_player_ghost()
best_skill_level = you.skills[best_skill];
xl = you.experience_level;
+ colour = mons_class_colour(MONS_PLAYER_GHOST);
fly = mons_class_flies(MONS_PLAYER_GHOST);
add_spells();
}
+static unsigned char _ugly_thing_random_colour()
+{
+ const unsigned char colours[] =
+ {
+ CYAN, GREEN, RED, LIGHTGREY, BROWN, MAGENTA
+ };
+
+ return (colours[random2(sizeof(colours) / sizeof(*colours))]);
+}
+
+static mon_attack_flavour _ugly_thing_colour_to_flavour(unsigned char u_colour)
+{
+ mon_attack_flavour u_att_flav = AF_PLAIN;
+
+ switch (u_colour)
+ {
+ case CYAN:
+ u_att_flav = AF_ELEC;
+ break;
+
+ case GREEN:
+ u_att_flav = AF_POISON;
+ break;
+
+ case RED:
+ u_att_flav = AF_FIRE;
+ break;
+
+ case LIGHTGREY:
+ u_att_flav = AF_COLD;
+ break;
+
+ case BROWN:
+ u_att_flav = AF_ACID;
+ break;
+
+ case MAGENTA:
+ u_att_flav = AF_DISEASE;
+ break;
+
+ default:
+ break;
+ }
+
+ return (u_att_flav);
+}
+
+static mon_attack_flavour _ugly_thing_flavour_upgrade(mon_attack_flavour u_att_flav)
+{
+ switch (u_att_flav)
+ {
+ case AF_POISON:
+ u_att_flav = AF_POISON_MEDIUM;
+ break;
+
+ case AF_FIRE:
+ u_att_flav = AF_NAPALM;
+ break;
+
+ case AF_DISEASE:
+ u_att_flav = AF_ROT;
+ break;
+
+ default:
+ break;
+ }
+
+ return (u_att_flav);
+}
+
+void ghost_demon::init_ugly_thing(bool very_ugly)
+{
+ // Midpoint: 10, as in mon-data.h.
+ speed = 9 + random2(3);
+
+ // Midpoint: 10, as in mon-data.h.
+ ev = 9 + random2(3);
+
+ // Midpoint: 3, as in mon-data.h.
+ ac = 2 + random2(3);
+
+ // Midpoint: 12, as in mon-data.h.
+ damage = 11 + random2(3);
+
+ // Experience level: 8, the same as in mon-data.h.
+ xl = 8;
+
+ // Hit dice: {8, 3, 5, 0}, the same as in mon-data.h.
+ max_hp = hit_points(xl, 3, 5);
+
+ resists.elec = 0;
+ resists.poison = 0;
+ resists.fire = 0;
+ resists.cold = 0;
+ resists.acid = 0;
+ resists.sticky_flame = false;
+
+ // An ugly thing gets one random resistance.
+ ugly_thing_add_resistance();
+
+ const mon_attack_type att_types[] =
+ {
+ AT_BITE, AT_STING, AT_CLAW, AT_PUNCH, AT_KICK, AT_TENTACLE_SLAP,
+ AT_TAIL_SLAP, AT_BUTT
+ };
+
+ att_type = att_types[random2(sizeof(att_types) / sizeof(*att_types))];
+
+ // An ugly thing always gets a low-intensity colour.
+ colour = _ugly_thing_random_colour();
+
+ // Pick a compatible attack flavour for this colour.
+ att_flav = _ugly_thing_colour_to_flavour(colour);
+
+ // If this is a very ugly thing, upgrade it properly.
+ if (very_ugly)
+ ugly_thing_to_very_ugly_thing();
+}
+
+void ghost_demon::ugly_thing_to_very_ugly_thing()
+{
+ // Midpoint when added to an ugly thing: 4, as in mon-data.h.
+ ac++;
+
+ // Midpoint when added to an ugly thing: 17, as in mon-data.h.
+ damage += 5;
+
+ // Experience level when added to an ugly thing: 12, the same as in
+ // mon-data.h.
+ xl += 4;
+
+ // Hit dice when added to an ugly thing: {12, 3, 5, 0}, the same as
+ // in mon-data.h.
+ max_hp += hit_points(4, 3, 5);
+
+ // A very ugly thing always gets a high-intensity colour.
+ colour = make_high_colour(colour);
+
+ // A very ugly thing sometimes gets a stronger attack flavour.
+ if (one_chance_in(3))
+ att_flav = _ugly_thing_flavour_upgrade(att_flav);
+
+ // A very ugly thing gets one more random resistance, and another
+ // possible resistance based on its stronger attack flavour.
+ ugly_thing_add_resistance();
+}
+
+void ghost_demon::ugly_thing_add_resistance()
+{
+ int base_rand = 6;
+ if (resists.sticky_flame)
+ base_rand--;
+
+ switch (random2(base_rand))
+ {
+ case 0:
+ resists.elec++;
+ break;
+
+ case 1:
+ resists.poison++;
+ break;
+
+ case 2:
+ resists.fire++;
+ break;
+
+ case 3:
+ resists.cold++;
+ break;
+
+ case 4:
+ resists.acid++;
+ break;
+
+ case 5:
+ resists.sticky_flame = true;
+ break;
+ }
+
+ // Guarantee certain resistances for stronger attack flavours.
+ if (att_flav == AF_POISON_MEDIUM && !resists.poison)
+ resists.poison++;
+ else if (att_flav == AF_ACID && !resists.acid)
+ resists.acid++;
+ else if (att_flav == AF_NAPALM && !resists.sticky_flame)
+ resists.sticky_flame = true;
+}
+
static spell_type search_first_list(int ignore_spell)
{
for (unsigned i = 0;
diff --git a/crawl-ref/source/ghost.h b/crawl-ref/source/ghost.h
index d10a664c68..f7f9dafb96 100644
--- a/crawl-ref/source/ghost.h
+++ b/crawl-ref/source/ghost.h
@@ -31,9 +31,12 @@ public:
short max_hp, ev, ac, damage, speed;
bool see_invis;
brand_type brand;
+ mon_attack_type att_type;
+ mon_attack_flavour att_flav;
mon_resist_def resists;
bool spellcaster, cycle_colours;
+ unsigned char colour;
flight_type fly;
monster_spells spells;
@@ -43,6 +46,8 @@ public:
void reset();
void init_random_demon();
void init_player_ghost();
+ void init_ugly_thing(bool very_ugly);
+ void ugly_thing_to_very_ugly_thing();
public:
static std::vector<ghost_demon> find_ghosts();
@@ -56,6 +61,7 @@ private:
private:
void add_spells();
spell_type translate_spell(spell_type playerspell) const;
+ void ugly_thing_add_resistance();
};
bool debug_check_ghosts();
diff --git a/crawl-ref/source/mgrow.cc b/crawl-ref/source/mgrow.cc
index a1bd83cc4d..490c1ec308 100644
--- a/crawl-ref/source/mgrow.cc
+++ b/crawl-ref/source/mgrow.cc
@@ -10,6 +10,7 @@
REVISION("$Rev$");
#include "enum.h"
+#include "ghost.h"
#include "mgrow.h"
#include "mon-util.h"
#include "monstuff.h"
@@ -138,6 +139,16 @@ void monsters::upgrade_type(monster_type after, bool adjust_hd,
hit_points = std::min(hit_points, max_hit_points);
}
}
+
+ // An ugly thing is the only ghost demon monster that can level up.
+ // If one has leveled up to a very ugly thing, upgrade it properly.
+ //
+ // XXX: There should be a better way to do this!
+ if (type == MONS_VERY_UGLY_THING)
+ {
+ ghost->ugly_thing_to_very_ugly_thing();
+ uglything_init();
+ }
}
bool monsters::level_up_change()
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index 342ad16205..0d46a78547 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -1357,9 +1357,9 @@ static monsterentry mondata[] = {
// ugly things ('u')
{
- MONS_UGLY_THING, 'u', BROWN, "ugly thing",
+ MONS_UGLY_THING, 'u', BLACK, "ugly thing",
M_WARM_BLOOD,
- mrd(MR_RES_COLD, 2),
+ MR_NO_FLAGS,
600, 10, MONS_UGLY_THING, MONS_UGLY_THING, MH_NATURAL, -3,
{ {AT_HIT, AF_PLAIN, 12}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
{ 8, 3, 5, 0 },
@@ -1368,14 +1368,14 @@ static monsterentry mondata[] = {
},
{
- MONS_VERY_UGLY_THING, 'u', RED, "very ugly thing",
+ MONS_VERY_UGLY_THING, 'u', BLACK, "very ugly thing",
M_WARM_BLOOD,
- mrd(MR_RES_COLD, 2),
+ MR_NO_FLAGS,
750, 10, MONS_UGLY_THING, MONS_VERY_UGLY_THING, MH_NATURAL, -3,
{ {AT_HIT, AF_PLAIN, 17}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
{ 12, 3, 5, 0 },
- 4, 8, MST_NO_SPELLS, CE_MUTAGEN_RANDOM, Z_BIG, S_ROAR, I_ANIMAL,
- HT_AMPHIBIOUS_LAND, 8, DEFAULT_ENERGY, MONUSE_OPEN_DOORS, MONEAT_NOTHING, SIZE_LARGE
+ 4, 10, MST_NO_SPELLS, CE_MUTAGEN_RANDOM, Z_BIG, S_ROAR, I_ANIMAL,
+ HT_AMPHIBIOUS_LAND, 10, DEFAULT_ENERGY, MONUSE_OPEN_DOORS, MONEAT_NOTHING, SIZE_LARGE
},
// vortices ('v')
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 0b59250376..14721142ff 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -588,6 +588,9 @@ bool mons_is_chaotic(const monsters *mon)
if (mons_is_shapeshifter(mon))
return (true);
+ if (mon->type == MONS_UGLY_THING || mon->type == MONS_VERY_UGLY_THING)
+ return (true);
+
if (mon->has_spell(SPELL_POLYMORPH_OTHER))
return (true);
@@ -869,7 +872,9 @@ shout_type mons_shouts(int mc, bool demon_shout)
bool mons_is_ghost_demon(int mc)
{
- return (mc == MONS_PLAYER_GHOST
+ return (mc == MONS_UGLY_THING
+ || mc == MONS_VERY_UGLY_THING
+ || mc == MONS_PLAYER_GHOST
|| mc == MONS_PANDEMONIUM_DEMON);
}
@@ -1151,7 +1156,11 @@ mon_attack_def mons_attack_spec(const monsters *mon, int attk_number)
if (mons_is_ghost_demon(mc))
{
if (attk_number == 0)
- return (mon_attack_def::attk(mon->ghost->damage));
+ {
+ return (mon_attack_def::attk(mon->ghost->damage,
+ mon->ghost->att_type,
+ mon->ghost->att_flav));
+ }
return (mon_attack_def::attk(0, AT_NONE));
}
@@ -6261,10 +6270,12 @@ void monsters::slow_down(actor *atk, int strength)
enchant_monster_with_flavour(this, atk, BEAM_SLOW, strength);
}
-void monsters::set_ghost(const ghost_demon &g)
+void monsters::set_ghost(const ghost_demon &g, bool has_name)
{
ghost.reset(new ghost_demon(g));
- mname = ghost->name;
+
+ if (has_name)
+ mname = ghost->name;
}
void monsters::pandemon_init()
@@ -6287,7 +6298,7 @@ void monsters::pandemon_init()
if (you.char_direction == GDT_ASCENDING && you.level_type == LEVEL_DUNGEON)
colour = LIGHTRED;
else
- colour = random_colour(); // demon's colour
+ colour = ghost->colour;
load_spells(MST_GHOST);
}
@@ -6308,7 +6319,7 @@ void monsters::ghost_init()
flags = MF_INTERESTING;
foe = MHITNOT;
foe_memory = 0;
- colour = mons_class_colour(MONS_PLAYER_GHOST);
+ colour = ghost->colour;
number = MONS_PROGRAM_BUG;
load_spells(MST_GHOST);
@@ -6319,6 +6330,18 @@ void monsters::ghost_init()
find_place_to_live();
}
+void monsters::uglything_init()
+{
+ hit_dice = ghost->xl;
+ hit_points = ghost->max_hp;
+ max_hit_points = ghost->max_hp;
+ ac = ghost->ac;
+ ev = ghost->ev;
+ speed = ghost->speed;
+ speed_increment = 70;
+ colour = ghost->colour;
+}
+
bool monsters::check_set_valid_home(const coord_def &place,
coord_def &chosen,
int &nvalid) const
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index a3022f0d4c..a3d1c326af 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -1237,8 +1237,16 @@ static int _place_monster_aux(const mgen_data &mg,
}
menv[id].foe = mg.foe;
- // Initialise pandemonium demons.
- if (menv[id].type == MONS_PANDEMONIUM_DEMON)
+ // Initialise (very) ugly things and pandemonium demons.
+ if (menv[id].type == MONS_UGLY_THING
+ || menv[id].type == MONS_VERY_UGLY_THING)
+ {
+ ghost_demon ghost;
+ ghost.init_ugly_thing(menv[id].type == MONS_VERY_UGLY_THING);
+ menv[id].set_ghost(ghost, false);
+ menv[id].uglything_init();
+ }
+ else if (menv[id].type == MONS_PANDEMONIUM_DEMON)
{
ghost_demon ghost;
ghost.init_random_demon();
diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc
index b9b55300eb..89ac13703f 100644
--- a/crawl-ref/source/stuff.cc
+++ b/crawl-ref/source/stuff.cc
@@ -1340,6 +1340,22 @@ unsigned char random_uncommon_colour()
return (result);
}
+unsigned char make_low_colour(unsigned char colour)
+{
+ if (colour >= 8 && colour <= 15)
+ return (colour - 8);
+
+ return (colour);
+}
+
+unsigned char make_high_colour(unsigned char colour)
+{
+ if (colour >= 0 && colour <= 7)
+ return (colour + 8);
+
+ return (colour);
+}
+
// returns if a colour is one of the special element colours (ie not regular)
bool is_element_colour( int col )
{
diff --git a/crawl-ref/source/stuff.h b/crawl-ref/source/stuff.h
index 11a6cff013..aa3d51916e 100644
--- a/crawl-ref/source/stuff.h
+++ b/crawl-ref/source/stuff.h
@@ -194,6 +194,8 @@ bool player_can_hear(const coord_def& p);
unsigned char random_colour();
unsigned char random_uncommon_colour();
+unsigned char make_low_colour(unsigned char colour);
+unsigned char make_high_colour(unsigned char colour);
bool is_element_colour( int col );
int element_colour( int element, bool no_random = false );
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index 5db90d707d..4d133247f1 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -2453,11 +2453,14 @@ static void marshallGhost(writer &th, const ghost_demon &ghost)
marshallShort(th, ghost.speed);
marshallByte(th, ghost.see_invis);
marshallShort(th, ghost.brand);
+ marshallShort(th, ghost.att_type);
+ marshallShort(th, ghost.att_flav);
marshallResists(th, ghost.resists);
marshallByte(th, ghost.spellcaster);
marshallByte(th, ghost.cycle_colours);
+ marshallByte(th, ghost.colour);
marshallShort(th, ghost.fly);
marshallSpells(th, ghost.spells);
@@ -2486,10 +2489,20 @@ static ghost_demon unmarshallGhost(reader &th, char minorVersion)
ghost.see_invis = unmarshallByte(th);
ghost.brand = static_cast<brand_type>( unmarshallShort(th) );
+ if (minorVersion >= TAG_MINOR_UGLY)
+ {
+ ghost.att_type = static_cast<mon_attack_type>( unmarshallShort(th) );
+ ghost.att_flav = static_cast<mon_attack_flavour>( unmarshallShort(th) );
+ }
+
unmarshallResists(th, ghost.resists);
ghost.spellcaster = unmarshallByte(th);
ghost.cycle_colours = unmarshallByte(th);
+
+ if (minorVersion >= TAG_MINOR_UGLY)
+ ghost.colour = unmarshallByte(th);
+
ghost.fly = static_cast<flight_type>( unmarshallShort(th) );
unmarshallSpells(th, ghost.spells);
diff --git a/crawl-ref/source/tags.h b/crawl-ref/source/tags.h
index 0535dbefad..4828196753 100644
--- a/crawl-ref/source/tags.h
+++ b/crawl-ref/source/tags.h
@@ -70,7 +70,8 @@ enum tag_minor_version
TAG_MINOR_ZOT_OPEN = 18, // Remember whether Zot was opened.
TAG_MINOR_JELLY = 19, // Remember whether the royal jelly is dead.
TAG_ANNOTATE_EXCL = 20, // Store exclusion information for annotations.
- TAG_MINOR_VERSION = 20 // Current version. (Keep equal to max.)
+ TAG_MINOR_UGLY = 21, // More ghost bits for (very) ugly things.
+ TAG_MINOR_VERSION = 21 // Current version. (Keep equal to max.)
};