void CreatureAttributes::consume(Creature* self, const CreatureAttributes& other) { Debug() << name->bare() << " consume " << other.name->bare(); self->you(MsgType::CONSUME, other.name->the()); consumeBodyParts(self, other); if (other.isHumanoid() && !isHumanoid() && numBodyParts(BodyPart::ARM) >= 2 && numBodyParts(BodyPart::LEG) >= 2 && numBodyParts(BodyPart::HEAD) >= 1) { self->you(MsgType::BECOME, "a humanoid"); self->addPersonalEvent(getName().the() + " turns into a humanoid"); humanoid = true; } vector<string> adjectives; for (auto t : ENUM_ALL(AttrType)) consumeAttr(attr[t], other.attr[t], adjectives, getAttrNameMore(t)); consumeAttr(*size, *other.size, adjectives, "larger"); consumeAttr(*weight, *other.weight, adjectives, ""); consumeAttr(barehandedDamage, other.barehandedDamage, adjectives, "more dangerous"); consumeAttr(barehandedAttack, other.barehandedAttack, adjectives, ""); consumeAttr(attackEffect, other.attackEffect, adjectives, ""); consumeAttr(passiveAttack, other.passiveAttack, adjectives, ""); consumeAttr(gender, other.gender, adjectives); consumeAttr(skills, other.skills, adjectives); if (!adjectives.empty()) { self->you(MsgType::BECOME, combine(adjectives)); self->addPersonalEvent(getName().the() + " becomes " + combine(adjectives)); } consumeBodyParts(self,other); consumeEffects(other.permanentEffects); }
optional<Sound> CreatureAttributes::getDeathSound() const { if (noDyingSound) return none; else return Sound(dyingSound ? *dyingSound : isHumanoid() ? SoundId::HUMANOID_DEATH : SoundId::BEAST_DEATH) .setPitch(getDeathSoundPitch(getSize())); }
AttackType CreatureAttributes::getAttackType(const Item* weapon) const { if (weapon) return weapon->getAttackType(); else if (barehandedAttack) return *barehandedAttack; else return isHumanoid() ? AttackType::PUNCH : AttackType::BITE; }
string CreatureAttributes::getDescription() const { if (!isSpecial) return ""; string attack; if (attackEffect) attack = " It has a " + Effect::getName(*attackEffect) + " attack."; return adjectives(getSize(), isUndead(), notLiving) + (isHumanoid() ? " humanoid" : " beast") + (!isCorporal() ? " spirit" : "") + bodyDescription() + ". " + attack; }
vector<AttackLevel> CreatureAttributes::getAttackLevels() const { if (isHumanoid() && !numGood(BodyPart::ARM)) return {AttackLevel::LOW}; switch (getSize()) { case CreatureSize::SMALL: return {AttackLevel::LOW}; case CreatureSize::MEDIUM: return {AttackLevel::LOW, AttackLevel::MIDDLE}; case CreatureSize::LARGE: return {AttackLevel::LOW, AttackLevel::MIDDLE, AttackLevel::HIGH}; case CreatureSize::HUGE: return {AttackLevel::MIDDLE, AttackLevel::HIGH}; } }
string CreatureAttributes::bodyDescription() const { vector<string> ret; for (BodyPart part : {BodyPart::ARM, BodyPart::LEG, BodyPart::WING}) if (int num = numBodyParts(part)) ret.push_back(getPlural(getBodyPartName(part), num)); if (isHumanoid() && numBodyParts(BodyPart::HEAD) == 0) ret.push_back("no head"); if (ret.size() > 0) return " with " + combine(ret); else return ""; }
void draw_monsters() { short i,j = 0,k; short width,height; rectangle source_rect,to_rect; location where_draw,store_loc; ter_num_t ter; rectangle monst_rects[4][4] = { {{0,0,36,28}}, {{0,7,18,21},{18,7,36,21}}, {{9,0,27,14},{9,14,27,28}}, {{0,0,18,14},{0,14,18,28},{18,0,36,14},{18,14,36,28}} }; if(is_out()) for(i = 0; i < 10; i++) if(univ.party.out_c[i].exists) { if((point_onscreen(univ.party.p_loc, univ.party.out_c[i].m_loc)) && (can_see_light(univ.party.p_loc, univ.party.out_c[i].m_loc,sight_obscurity) < 5)) { where_draw.x = univ.party.out_c[i].m_loc.x - univ.party.p_loc.x + 4; where_draw.y = univ.party.out_c[i].m_loc.y - univ.party.p_loc.y + 4; for(j = 0; univ.party.out_c[i].what_monst.monst[j] == 0 && j < 7; j++); short picture_wanted; if(j == 7) univ.party.out_c[i].exists = false; // begin watch out else { picture_wanted = get_monst_picnum(univ.party.out_c[i].what_monst.monst[j]); } // end watch out if(univ.party.out_c[i].exists) { get_monst_dims(univ.party.out_c[i].what_monst.monst[j],&width,&height); if(picture_wanted >= 1000) { for(k = 0; k < width * height; k++) { sf::Texture* src_gw; graf_pos_ref(src_gw, source_rect) = spec_scen_g.find_graphic(picture_wanted % 1000 + ((univ.party.out_c[i].direction < 4) ? 0 : (width * height)) + k); to_rect = monst_rects[(width - 1) * 2 + height - 1][k]; to_rect.offset(13 + 28 * where_draw.x,13 + 36 * where_draw.y); rect_draw_some_item(*src_gw, source_rect, terrain_screen_gworld,to_rect, sf::BlendAlpha); } } if(picture_wanted < 1000) { for(k = 0; k < width * height; k++) { source_rect = get_monster_template_rect(picture_wanted,(univ.party.out_c[i].direction < 4) ? 0 : 1,k); to_rect = monst_rects[(width - 1) * 2 + height - 1][k]; to_rect.offset(13 + 28 * where_draw.x,13 + 36 * where_draw.y); int which_sheet = m_pic_index[picture_wanted].i / 20; sf::Texture& monst_gworld = *ResMgr::get<ImageRsrc>("monst" + std::to_string(1 + which_sheet)); rect_draw_some_item(monst_gworld, source_rect, terrain_screen_gworld,to_rect, sf::BlendAlpha); } } } } } if(is_town() || is_combat()) { for(i = 0; i < univ.town.monst.size(); i++) if(univ.town.monst[i].active != 0 && !univ.town.monst[i].invisible && univ.town.monst[i].status[eStatus::INVISIBLE] <= 0) if(point_onscreen(center,univ.town.monst[i].cur_loc) && party_can_see_monst(i)) { where_draw.x = univ.town.monst[i].cur_loc.x - center.x + 4; where_draw.y = univ.town.monst[i].cur_loc.y - center.y + 4; get_monst_dims(univ.town.monst[i].number,&width,&height); for(k = 0; k < width * height; k++) { store_loc = where_draw; store_loc.x += k % width; store_loc.y += k / width; ter = univ.town->terrain(univ.town.monst[i].cur_loc.x,univ.town.monst[i].cur_loc.y); // in bed? if(store_loc.x >= 0 && store_loc.x < 9 && store_loc.y >= 0 && store_loc.y < 9 && (univ.scenario.ter_types[ter].special == eTerSpec::BED) && isHumanoid(univ.town.monst[i].m_type) && (univ.town.monst[i].active == 1 || univ.town.monst[i].target == 6) && width == 1 && height == 1) draw_one_terrain_spot((short) where_draw.x,(short) where_draw.y,10000 + univ.scenario.ter_types[ter].flag1); else if(univ.town.monst[i].picture_num >= 1000) { bool isParty = univ.town.monst[i].picture_num >= 10000; sf::Texture* src_gw; pic_num_t need_pic = (univ.town.monst[i].picture_num % 1000) + k; if(univ.town.monst[i].direction >= 4) need_pic += width * height; if(combat_posing_monster == i + 100) need_pic += (2 * width * height); graf_pos_ref(src_gw, source_rect) = spec_scen_g.find_graphic(need_pic, isParty); Draw_Some_Item(*src_gw, source_rect, terrain_screen_gworld, store_loc, 1, 0); } else { pic_num_t this_monst = univ.town.monst[i].picture_num; int pic_mode = (univ.town.monst[i].direction) < 4 ? 0 : 1; pic_mode += (combat_posing_monster == i + 100) ? 10 : 0; source_rect = get_monster_template_rect(this_monst, pic_mode, k); int which_sheet = m_pic_index[this_monst].i / 20; sf::Texture& monst_gworld = *ResMgr::get<ImageRsrc>("monst" + std::to_string(1 + which_sheet)); Draw_Some_Item(monst_gworld, source_rect, terrain_screen_gworld, store_loc, 1, 0); } } } } }