monster_polymorph(), as it still doesn't do everything needed. Replace it with monsters::change_type(), split out from monsters::level_up_change(), which does do everything needed, and in a cleaner way. Unfortunately, it's still a hack, but it should be easier to deal with for now. Sorry for the mess.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3783 c06c8d41-db1a-0410-9941-cceddc491573
V7IKAPO5OY7CJTT62GMHQOD3EQW42FTTY3KDBOTJUODPS5WMBCHAC
CWQITHQHCEGZLXYQ26OQ6PJSWPQ6Z2DBLARLGTV332LKSF7HSENQC
Z75MWMOPGK3RC3ERIV5AW52CRJDTYWLXYGE6CHRF4MCB5EJ7WH6QC
RIIO4BI64ECFXSRLBP3RA24QOPYXJVWMSFHLNTKUZS5YCLISLVJQC
HOPP345EQLSF24XJYE3625VKU23PBKM5ZZKNCXBXUWYYORYPMDAAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
USSKCWQTF6BTE3SFLQVCT6RZHU2R7URWFC7EPO2EN3Z6U4IEQ7GQC
KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC
VD5OPYZ3YO5L7GFKWPCMT3WXTDPUIIYGMJIOQEWNZLZSHH5L6RYQC
LJ7HIRLTL5KHP3DJP57KRDH3PHZIS37HNC4SLZGK2ZQI2WTQBOPAC
OSGS3PH2L5CBTDVZCZS6OCFQNA4A7RMEXBYJQB7DDZBYYJW7QSSAC
2SMZGNBB352OJBIT2UE3NONODTTMV3FJJFBQUN4VNLLNYJKTJKBQC
5ZYOO2RVGH53ONV4U5NO6MTINQXET6GV6TETPVCFAVOX44LDNR4QC
BRGAZR5AXWC2IALBVXO5SB354IRQEIRHSK55RZPGFI4AGIOD4LUQC
4UXFU3FZOCBSLDQ4S7MJKAE2H7VUHCNRDQMIY6NJ3PHYXWNGISDQC
74LQ7JXVLAFSHLI7LCBKFX47CNTYSKGUQSXNX5FCIUIGCC2JTR3QC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
5UC5TI7B6NWGIGN74QRBZKDBYUMHLM2ZO5ATXEZ6TZOGOLF3JX5QC
CDKRLJIGVWQE2PMHCSLJBLYQEK7JYC4LQM7H2X3O6NMJMCCDRVIAC
7AMQN7MITMXBNVDAK5VOXTQ4TZIAOD6ZLOFJG7GQMBTY23Y2BKSAC
5XSXMOBGXFLTIQE6WDXWWFVDOTUPZSIQ2FWT3YI5QMVU6D76IUYQC
TVC7W7C2XKBQSD2IJFMWFVGXZAOD4EUOW43NAQTOF5KFMAUOJABQC
// Turn an ordinary monster into a priestly monster.
monster_change_type(mon, priest_type);
// Turn an ordinary monster into a priestly monster, using a
// function normally used when going up an experience level.
// This is a hack, but there seems to be no better way for now.
mon->change_type(priest_type, true);
}
// Change one monster type into another. This preserves as much as
// possible between types, so, if the two types are radically different,
// some special handling may be needed after calling this.
void monster_change_type(monsters *monster, monster_type targetc)
{
const unsigned long old_flags = monster->flags;
const unsigned long old_exp = monster->experience;
const int old_hp = monster->hit_points;
const int old_hp_max = monster->max_hit_points;
const char old_ench_countdown = monster->ench_countdown;
const bool old_mon_caught = mons_is_caught(monster);
/* deal with mons_sec */
monster->type = targetc;
monster->number = MONS_PROGRAM_BUG;
mon_enchant abj = monster->get_ench(ENCH_ABJ);
mon_enchant shifter = monster->get_ench(ENCH_GLOWING_SHAPESHIFTER,
ENCH_SHAPESHIFTER);
// Note: define_monster() will clear out all enchantments! -- bwr
define_monster( monster_index(monster) );
monster->flags = old_flags;
monster->gain_exp(old_exp);
monster->add_ench(abj);
monster->add_ench(shifter);
monster->ench_countdown = old_ench_countdown;
if (mons_class_flag( monster->type, M_INVIS ))
monster->add_ench(ENCH_INVIS);
monster->hit_points = monster->max_hit_points
* ((old_hp * 100) / old_hp_max) / 100;
monster->fix_speed();
if (old_mon_caught)
monster->add_ench(ENCH_HELD);
// randomize things:
monster->flags = 0L;
monster->experience = 0L;
/* deal with mons_sec */
monster->type = targetc;
monster->number = MONS_PROGRAM_BUG;
mon_enchant abj = monster->get_ench(ENCH_ABJ);
mon_enchant shifter = monster->get_ench(ENCH_GLOWING_SHAPESHIFTER,
ENCH_SHAPESHIFTER);
monster->hit_points = monster->max_hit_points
* ((old_hp * 100) / old_hp_max) / 100
+ random2(monster->max_hit_points);
if (monster->hit_points > monster->max_hit_points)
monster->hit_points = monster->max_hit_points;
monster->speed_increment = 67 + random2(6);
monster_drop_ething(monster);
mons_clear_trapping_net(monster);
const int net = get_trapping_net(monster->x, monster->y);
if (net != NON_ITEM)
remove_item_stationary(mitm[net]);
if (const monster_level_up *lup =
monster_level_up_target(static_cast<monster_type>(type), hit_dice))
{
const monsterentry *orig = get_monster_data(type);
// Ta-da!
type = lup->after;
const monsterentry *orig = get_monster_data(type);
// Ta-da!
type = after;
const int minhp = dummy.max_hit_points;
if (max_hit_points < minhp)
{
hit_points += minhp - max_hit_points;
max_hit_points = minhp;
hit_points = std::min(hit_points, max_hit_points);
}
hit_points += minhp - max_hit_points;
max_hit_points = minhp;
hit_points = std::min(hit_points, max_hit_points);