Encapsulate filling out a corpse object for a particular monster in fill_out_corpse().
Started work on "swap chaos weapon with weapon of victim" chaos effect, but am putting that off until there's some actor class virtual methods for changing inventory and equipment.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7807 c06c8d41-db1a-0410-9941-cceddc491573
UPA65AL4JXYLIHH4D42IWJHRTOAF2BPOVZOAKOXBLZBYIMDZDFFQC XJNJEBODVL4WPMFYJ3MTF3KAWLURBIZPIIC7GGRKTL2FAX7TLSLAC SZ2WVDRM5X23JFNNW6HTWNQ2DECTIXBU7EVOQRDISPZJNLJF2QBQC XDDH7FKCSFL76UFBC2VEX4AS23R7Y75HINAOGSW3RZSBBGMVIUGAC ZX6XMFMK46FKFKJZGLSKQM2Z6GKCBMJU2PLOWMSN2D6OXQE4VI3QC 7EIA4DGVDBJRNHEAN3DK6SNHGALSSEUWSOL57C2VPGN2IZCQ633AC KVDUZCENP2TCYLWIGUOS4JD4PK4TIJE5GGCAXVUBAYSF5YZFADVAC 47ADGRNSYVDBHB3JFKPZT7AUVWYTR54SCFMGGCQR2LWOUHAERQ3QC AYU5OVG2HZO46KDAPKUWAVHS5HTYFKUWIMIRMTHAXVVFEDJE7YPAC SOCJXX6MMOXLBEWBID4QN5FW2YNYULNNN7K3IRL7RSWK5EUNAZLQC IXLNOTBJGHKESBCTME6QAR6XVWFNCHYGMS62V62ZJEA7VLQHXO2QC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC WDQ3ST3BQ7BMW2IXQMSJVRG7GK2EG444JLKII24FB7IJ5YF5KT5QC J7GPW2YXLT6FGSKJ24FGQ24GTRZ6A2BDYM6CIXV4R6YBEHP6BGPAC HIPFIMUOA7DFOFV3DQ55YZJVGNU2GNDYFUCB4MRPUR5DTYDO5YMAC RM2JXW3ATVYRYHF3NMG5ALGI64OJ7IP2F3MDUDPUT5TBKSSN4KVQC AV3TMWHWB3XBXQCT34UPMZBSIIKVXIGWQPNEFU4CZSBS3ZOF2CUQC TGJZXTUIAKCFZQJ54ZQEBGFBVZSJCAX6AWDRSH3TP7UJRLGUM5SAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC SCXTTP2FDNB2A7F4XXGXSSOEKZQ7ODDGN5YBCTZXGZ22CLCEH3WQC DZD6YG52TXNI4CJ2FRGFULBH6G5MDLRVQV3X3V35AW533Z3TVBKAC 247OW5JFN34ZV3GRVHRE25AXLLISUBPOX5YRGUE64BCM2V7QNEHAC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC QDTVLBRGHDTRUVT7I3O72K6TMOYAUSAJBZUHGOEFU2RKJNUPWZSQC SIDH2P7NBIG5KEOE27XHD3ZT2NQ2OJZFN6VZXWNWYFFY5YVXSSVQC ZHFUXYUHS6V47WK2NRH7OU6RX77NRKTXOZC3MND2GG7PEEWSGFTAC GACH6PWPGGUBEE7PFEPQMOZKSR7HTQGL2WLGF2AQPJD3FCCSKZNQC NNG27Y5ZQAZX6UD7F7M4F6KEZBEDFXPEEC3LFUSX4ESKT7K6UJQAC 2UO6ZOW7UCP5XJ2TJ26PJNQABILK2BZ4J3BAKLOKMZPJDQHW24MAC 2YL37AGHLFOMIF3GCTVQGGV2RNNWETWM6ZMUHO3QEWDVBFFSFAKQC BNRY5YIXLFE2TDNU2JQHWWXJQVWNSEWQ52DU7XUWIT5DZWKGBDDAC EFWEYIB2R3DPD3JWIPU6LS6SFLPMYN7J7X4GBZR7DJWKHJ3UELSAC JGTKZP6HCXDHEJLAONL3FNLNIZ7MUBYKXZ4CRTL46YC53TW7CBEAC HHGJTYLLLXXUIFOWZDV7XEXBJT6I7OUCOCW5BALLX37LCN5FEKYAC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC 542UIZKI65UDRNEMGFFDBWYD5XC7AYLTZ3JZQRR2GHYJALD3YY6QC 3V52MSSK7QX7FWLLUW63DTWCBAJEK674EFZLKP45FLZ5KZKVARHAC C67GX7W5HBCDPQJRSHWMLM4DUJ3ELFSHH42SVICFJVCJW25T5Z3AC QS3ZRS3E6KL3YJHPKYEWCWJYRBJSXD5OOYF6Y25HZVECGPJRDB5QC L254F6ZIU2HWGLFFGPIORTN4C3TDQ3E5JZ7Z7GQA5AEDIKL6PKDAC NRIZKLUO26UHNKB4IERXI6ECMD2IJYZACQNIUU3SH6BPLGHAJYVAC OWERGKLVPNPGIIS23FZ7ZDOBWUIXCKYAFG3URXU75JAUDX3N5ENAC 47RJZCYIM3B7IXJT7FFT6NBZZREY6REK5DZWKZ5E7G66BXEXFN6QC C6QWJ7O4HS2IGJZTDQLGFPXPD5OBFS4U364IRZFV7V2LXVPP4DXQC QKGDOYIYKE6B36ION5O2DRW65DWWPZMYNWJVH7LJJ7FPGGM2MYAQC JYEEOUYQ7ZPKOGWUV7VCORBVSOLF2UCBFBH3TR75RGOSS6PNKYUAC ASLW3Z5PAVZSWJEMMMVZT226P44EKSAD47QS72JIFJESAI3RPN3AC RBAGQ2PB7V5YAM5KSHSZR2E3MLKDSRVM5XYGI2TIXP5QMVBOQHDQC TV3ZC6WOZKSQQJQN26JIVKCHK6UK7WMDBYZDUYRWEAZ4JB4YVNAAC 3DQXSE4YGFBBDUWK4YEOFWW4UPWILWELFSLP37SL6BERGAZJC5YAC 5V47S4NNTHWTSAHV3YLO2VGH7JTUIYJ3GBPDN5ZM4UQALT2ZEXDQC }}}void _dgn_check_terrain_player(const coord_def pos){if (pos != you.pos())return;if (you.can_pass_through(pos) || !grid_is_solid(grd(pos))){if (!you.airborne()){// If the monster can't stay submerged in the new terrain// and there aren't any adjacent squares where it can// stay submerged then move it.if (mgrd(you.pos()) != NON_MONSTER&& !mons_is_submerged( &menv[ mgrd(you.pos()) ] )){monster_teleport( &menv[ mgrd(you.pos()) ], true, false);}move_player_to_grid(pos, false, true, false);
if (affect_player && pos == you.pos())
if (affect_player)_dgn_check_terrain_player(pos);set_terrain_changed(pos.x, pos.y);}bool swap_features(const coord_def &pos1, const coord_def &pos2,bool swap_everything){ASSERT(in_bounds(pos1) && in_bounds(pos2));ASSERT(pos1 != pos2);const dungeon_feature_type feat1 = grd(pos1);const dungeon_feature_type feat2 = grd(pos2);if (is_sanctuary(pos1) || is_sanctuary(pos2))return (false);if (is_notable_terrain(feat1) && !see_grid(pos1)&& is_terrain_known(pos1.x, pos1.y))
if (!grid_is_solid(grd(pos)))
return (false);}if (is_notable_terrain(feat2) && !see_grid(pos2)&& is_terrain_known(pos2.x, pos2.y)){return (false);}const unsigned short col1 = env.grid_colours(pos1);const unsigned short col2 = env.grid_colours(pos2);const unsigned long prop1 = env.map(pos1).property;const unsigned long prop2 = env.map(pos2).property;trap_def* trap1 = find_trap(pos1);trap_def* trap2 = find_trap(pos2);// Find a temporary holding place for pos1 stuff to be moved to// before pos2 is moved to pos1.coord_def temp(-1, -1);for (int x = X_BOUND_1 + 1; x < X_BOUND_2; x++){for (int y = Y_BOUND_1 + 1; y < Y_BOUND_2; y++)
// If the monster can't stay submerged in the new terrain// and there aren't any adjacent squares where it can// stay submerged then move it.if (mgrd(you.pos()) != NON_MONSTER&& !mons_is_submerged( &menv[ mgrd(you.pos()) ] )){monster_teleport( &menv[ mgrd(you.pos()) ], true, false);}move_player_to_grid(pos, false, true, false);
temp = pos;break;
set_terrain_changed(pos.x, pos.y);
if (!in_bounds(temp)){mpr("swap_features(): No boring squares on level?", MSGCH_ERROR);return (false);}(void) move_notable_thing(pos1, temp);env.markers.move(pos1, temp);dungeon_events.move_listeners(pos1, temp);grd(pos1) = DNGN_UNSEEN;env.map(pos1).property = 0;(void) move_notable_thing(pos2, pos1);env.markers.move(pos2, pos1);dungeon_events.move_listeners(pos2, pos1);grd(pos2) = feat1;grd(pos1) = feat2;env.map(pos1).property = prop2;env.map(pos2).property = prop1;(void) move_notable_thing(temp, pos2);env.markers.move(temp, pos2);dungeon_events.move_listeners(temp, pos2);env.grid_colours(pos1) = col2;env.grid_colours(pos2) = col1;if (trap1)trap1->pos = pos2;if (trap2)trap2->pos = pos1;if (!swap_everything){_dgn_check_terrain_items(pos1, false);_dgn_check_terrain_monsters(pos1);_dgn_check_terrain_player(pos1);set_terrain_changed(pos1.x, pos1.y);_dgn_check_terrain_items(pos2, false);_dgn_check_terrain_monsters(pos2);_dgn_check_terrain_player(pos2);set_terrain_changed(pos2.x, pos2.y);return (true);}const int i1 = igrd(pos1);const int i2 = igrd(pos2);igrd(pos1) = i2;igrd(pos2) = i1;const int m1 = mgrd(pos1);const int m2 = mgrd(pos1);mgrd(pos1) = m2;mgrd(pos2) = m1;move_cloud(env.cgrid(pos1), temp);move_cloud(env.cgrid(pos2), pos1);move_cloud(env.cgrid(temp), pos2);if (pos1 == you.pos()){you.position = pos2;viewwindow(true, false);}else if (pos2 == you.pos()){you.position = pos1;viewwindow(true, false);}set_terrain_changed(pos1.x, pos1.y);set_terrain_changed(pos2.x, pos2.y);return (false);
}bool actor::can_wield(const item_def* item, bool ignore_curse,bool ignore_brand, bool ignore_shield,bool ignore_transform) const{if (item == NULL){// Unarmed combat.item_def fake;fake.base_type = OBJ_UNASSIGNED;return can_wield(fake, ignore_curse, ignore_brand, ignore_transform);}elsereturn can_wield(*item, ignore_curse, ignore_brand, ignore_transform);}bool player::can_wield(const item_def& item, bool ignore_curse,bool ignore_brand, bool ignore_shield,bool ignore_transform) const{if (equip[EQ_WEAPON] != -1 && !ignore_curse){if (item_cursed(inv[equip[EQ_WEAPON]]))return (false);}// Unassigned means unarmed combat.const bool two_handed = item.base_type == OBJ_UNASSIGNED|| hands_reqd(item, body_size()) == HANDS_TWO;if (two_handed && !ignore_shield && equip[EQ_SHIELD] != -1)return (false);return could_wield(item, ignore_brand, ignore_transform);
}bool move_notable_thing(const coord_def& orig, const coord_def& dest){ASSERT(in_bounds(orig) && in_bounds(dest));ASSERT(orig != dest);ASSERT(!is_notable_terrain(grd(dest)));if (!is_notable_terrain(grd(orig)))return (false);level_pos pos1(level_id::current(), orig);level_pos pos2(level_id::current(), dest);shops_present[pos2] = shops_present[pos1];altars_present[pos2] = altars_present[pos1];portals_present[pos2] = portals_present[pos1];portal_vaults_present[pos2] = portal_vaults_present[pos1];portal_vault_notes[pos2] = portal_vault_notes[pos1];portal_vault_colours[pos2] = portal_vault_colours[pos1];unnotice_feature(pos1);return (true);
bool force = false;int corpse_class = mons_species(monster->type);
ASSERT(monster->type != -1 && monster->type != MONS_PROGRAM_BUG);corpse.clear();int summon_type;if (mons_is_summoned(monster, NULL, &summon_type)|| mons_enslaved_body_and_soul(monster)|| (monster->flags & (MF_BANISHED | MF_HARD_RESET))){return (-1);}int corpse_class = mons_species(monster->type);
if (mons_weight(corpse_class) == 0 || mons_enslaved_body_and_soul(monster)|| (!force && coinflip())){return;}
if (mons_weight(corpse_class) == 0 && !allow_weightless)return (-1);corpse.flags = 0;corpse.base_type = OBJ_CORPSES;corpse.plus = corpse_class;corpse.plus2 = 0; // butcher work donecorpse.sub_type = CORPSE_BODY;corpse.special = FRESHEST_CORPSE; // rot timecorpse.quantity = 1;corpse.orig_monnum = monster->type + 1;corpse.props[MONSTER_NUMBER] = short(monster->number);
mitm[o].flags = 0;mitm[o].base_type = OBJ_CORPSES;mitm[o].plus = corpse_class;mitm[o].plus2 = 0; // butcher work donemitm[o].sub_type = CORPSE_BODY;mitm[o].special = FRESHEST_CORPSE; // rot timemitm[o].colour = mons_class_colour(corpse_class);mitm[o].quantity = 1;mitm[o].props[MONSTER_NUMBER] = short(monster->number);
const int corpse_class = fill_out_corpse(monster, mitm[o]);
if (mitm[o].colour == BLACK)mitm[o].colour = monster->colour;
// Don't place a corpse? If a zombified monster is somehow capable// of leaving a corpse then always place it.const bool force = mons_class_is_zombified(monster->type);if (corpse_class == -1 || (!force && coinflip()))return;
bool monsters::can_wield(const item_def& item, bool ignore_curse,bool ignore_brand, bool ignore_shield,bool ignore_transform) const{// Monsters can only wield weapons or go unarmed (OBJ_UNASSIGNED// means unarmed)if (item.base_type != OBJ_WEAPONS && item.base_type != OBJ_UNASSIGNED)return (false);
// MF_HARD_RESET means that all items the monster is carrying will// disappear when it does, so it can't accept new items or give up// the ones it has.if (flags & MF_HARD_RESET)return (false);// Summoned items can only be held by summoned monsters.if ((item.flags & ISFLAG_SUMMONED) && !is_summoned())return (false);item_def* weap1 = NULL;if (inv[MSLOT_WEAPON] != NON_ITEM)weap1 = &mitm[inv[MSLOT_WEAPON]];int avail_slots = 1;item_def* weap2 = NULL;if (mons_wields_two_weapons(this)){if (!weap1 || hands_reqd(*weap1, body_size()) != HANDS_TWO)avail_slots = 2;const int offhand = mons_offhand_weapon_index(this);if (offhand != NON_ITEM)weap2 = &mitm[offhand];}// If we're already wielding it, then of course we can wield it.if (&item == weap1 || &item == weap2)return(true);// Barehanded needs two hands.const bool two_handed = item.base_type == OBJ_UNASSIGNED|| hands_reqd(item, body_size()) == HANDS_TWO;item_def* _shield = NULL;if (inv[MSLOT_SHIELD] != NON_ITEM){ASSERT(!(weap1 && weap2));if (!ignore_shield && two_handed)return (false);_shield = &mitm[inv[MSLOT_SHIELD]];}if (!ignore_curse){int num_cursed = 0;if (weap1 && item_cursed(*weap1))num_cursed++;if (weap2 && item_cursed(*weap2))num_cursed++;if (_shield && item_cursed(*_shield))num_cursed++;if (two_handed && num_cursed > 0 || num_cursed >= avail_slots)return (false);}return could_wield(item, ignore_brand, ignore_transform);}bool monsters::could_wield(const item_def &item, bool ignore_brand,bool /* ignore_transform */) const{ASSERT(is_valid_item(item));// These *are* weapons, so they can't wield another weapon.if (type == MONS_DANCING_WEAPON)return (false);// Monsters can't use fixed artefactsif (is_fixed_artefact(item))return (false);// Wimpy monsters (e.g. kobold, goblin) can't use halberds etc.if (!check_weapon_wieldable_size(item, body_size(PSIZE_BODY)))return (false);if (!ignore_brand){// Demonic/undead monsters won't use holy weapons.if (mons_is_unholy(this) && is_holy_item(item))return (false);// Holy monsters won't use demonic or chaotic weapons.if (mons_holiness(this) == MH_HOLY&& (is_evil_item(item) || get_weapon_brand(item) == SPWPN_CHAOS)){return (false);}}return (true);}
// Wimpy monsters (e.g. kobold, goblin) shouldn't pick up halberds etc.if (!check_weapon_wieldable_size(weap, body_size(PSIZE_BODY)))return (false);
// Demonic/undead monsters won't pick up holy wrath.if (get_weapon_brand(weap) == SPWPN_HOLY_WRATH && mons_is_unholy(this))return (false);// Holy monsters won't pick up demonic weapons.if (mons_holiness(this) == MH_HOLY && is_evil_item(weap))return (false);
const bool stair_is_marker = env.markers.find(orig_pos, MAT_ANY);
// Don't move around notable terrain the player is aware of if it's// out of sight.if (is_notable_terrain(stair_feat)&& is_terrain_known(orig_pos.x, orig_pos.y) && !see_grid(orig_pos)){return (false);}
dungeon_feature_type feat = grd(defender->pos());if (!grid_destroys_items(feat) && !grid_is_solid(feat)&& !grid_is_water(feat) && !grid_is_trap(feat, true)){dest = defender->pos();}// Don't try to swap two markers.if (stair_is_marker && env.markers.find(defender->pos(), MAT_ANY))dest.set(-1, -1);
dest = defender->pos();
// Don't try to swap two markers.if (stair_is_marker && env.markers.find(*ri, MAT_ANY))continue;dungeon_feature_type feat = grd(defender->pos());if (!grid_destroys_items(feat) && !grid_is_solid(feat)&& !grid_is_water(feat) && !grid_is_trap(feat, true))
if (_ok_dest_grid(*ri))
if (stair_is_marker){env.markers.move(orig_pos, dest);dungeon_events.move_listeners(orig_pos, dest);}else if (dest_is_marker){env.markers.move(dest, orig_pos);dungeon_events.move_listeners(dest, orig_pos);}
// Is player aware of it happening?
static void _find_remains(monsters* mon, int &corpse_class, int &corpse,int &last_item, std::vector<int> items)
static void _find_remains(monsters* mon, int &corpse_class, int &corpse_index,item_def &fake_corpse, int &last_item,std::vector<int> items)
if (corpse_class == MONS_DRACONIAN)corpse_class = draco_subspecies(mon);if (mon->has_ench(ENCH_SHAPESHIFTER))corpse_class = MONS_SHAPESHIFTER;else if (mon->has_ench(ENCH_GLOWING_SHAPESHIFTER))corpse_class = MONS_GLOWING_SHAPESHIFTER;
if (si->plus != corpse_class)break;// It should have just been dropped.if (corpse_freshness(*si) != FRESHEST_CORPSE)
if (si->orig_monnum != fake_corpse.orig_monnum|| si->plus != fake_corpse.plus|| si->plus2 != fake_corpse.plus2|| si->special != fake_corpse.special|| si->flags != fake_corpse.flags){
if (corpse != NON_ITEM || !mons_class_can_be_zombified(corpse_class))
if (corpse_index != NON_ITEM || !mons_class_can_be_zombified(corpse_class))return (false);// Good gods won't let their gifts/followers be raised as the undead.if (is_good_god(mon->god))
// Fake a corpseitem_def &corpse_item(mitm[idx]);corpse_item.base_type = OBJ_CORPSES;corpse_item.sub_type = CORPSE_BODY;corpse_item.plus = corpse_class;corpse_item.orig_monnum = mon->type + 1;corpse_item.pos = mon->pos();corpse_item.quantity = 1;corpse_item.props[MONSTER_NUMBER] = short(mon->number);
mitm[idx] = fake_corpse;mitm[idx].pos = mon->pos();
// Insert it in the item stack right after the monster's// last item, so it will be equipped with all the monster's// items.corpse_item.link = mitm[last_item].link;
// Insert it in the item stack right after the monster's last item, so// it will be equipped with all the monster's items.mitm[idx].link = mitm[last_item].link;
if (animate_remains(mon->pos(), CORPSE_BODY, mon->behaviour,mon->foe, mon->god, true, true)){if (you.can_see(mon))simple_monster_message(mon," instantly turns into a zombie!");else if (see_grid(mon->pos()))mpr("A zombie appears out of nowhere!");return (true);}
// No equipment to get, or couldn't get it for some reason.if (zombie_index == -1){monster_type type = (mons_zombie_size(mon->type) == Z_SMALL) ?MONS_ZOMBIE_SMALL : MONS_ZOMBIE_LARGE;zombie_index = create_monster(mgen_data(type, mon->behaviour, 0, mon->pos(),mon->foe, MG_FORCE_PLACE, mon->god,(monster_type) mon->type, mon->number));
return (false);
if (zombie_index == -1)return (false);monsters *zombie = &menv[zombie_index];// Attempt to force zombie into exact same spot.if (zombie->pos() != mon->pos() && zombie->is_habitable(mon->pos()))zombie->move_to_pos(mon->pos());if (you.can_see(mon)){if (you.can_see(zombie))simple_monster_message(mon, " instantly turns into a zombie!");else if (last_item != NON_ITEM)simple_monster_message(mon, "'s equipment vanishes!");}elsesimple_monster_message(zombie, " appears from thin air!");return (true);
bool can_wield(const item_def* item,bool ignore_curse = false,bool ignore_brand = false,bool ignore_shield = false,bool ignore_transform = false) const;virtual bool can_wield(const item_def &item,bool ignore_curse = false,bool ignore_brand = false,bool ignore_shield = false,bool ignore_transform = false) const = 0;virtual bool could_wield(const item_def &item,bool ignore_brand = false,bool ignore_transform = false) const = 0;