void mdeath::normal(monster *z) { if ((g->u.sees(*z)) && (!z->no_corpse_quiet)) { add_msg(m_good, _("The %s dies!"), z->name().c_str()); //Currently it is possible to get multiple messages that a monster died. } if ( z->type->in_species( ZOMBIE )) { sfx::play_variant_sound( "mon_death", "zombie_death", sfx::get_heard_volume(z->pos())); } m_size monSize = (z->type->size); bool leaveCorpse = !((z->type->has_flag(MF_VERMIN)) || (z->no_corpse_quiet)); // leave some blood if we have to if (!z->has_flag(MF_VERMIN)) { field_id type_blood = z->bloodType(); if (type_blood != fd_null) { g->m.add_field( z->pos(), type_blood, 1, 0 ); } } int maxHP = z->get_hp_max(); if (!maxHP) { maxHP = 1; } float overflowDamage = std::max( -z->get_hp(), 0 ); float corpseDamage = 5 * (overflowDamage / (maxHP * 2)); if (leaveCorpse) { int gibAmount = int(floor(corpseDamage)) - 1; // allow one extra gib per 5 HP int gibLimit = 1 + (maxHP / 5.0); if (gibAmount > gibLimit) { gibAmount = gibLimit; } bool pulverized = (corpseDamage > 5 && overflowDamage > 150); if (!pulverized) { make_mon_corpse(z, int(floor(corpseDamage))); } else if (monSize >= MS_MEDIUM) { gibAmount += rng(1, 6); sfx::play_variant_sound( "mon_death", "zombie_gibbed", sfx::get_heard_volume(z->pos())); } // Limit chunking to flesh, veggy and insect creatures until other kinds are supported. bool leaveGibs = (z->made_of("flesh") || z->made_of("hflesh") || z->made_of("veggy") || z->made_of("iflesh")); if (leaveGibs) { make_gibs( z, gibAmount ); } } }
void mdeath::normal(monster *z) { if (g->u_see(z)) { g->add_msg(_("The %s dies!"), z->name().c_str()); } if(z->type->difficulty >= 30) { // TODO: might not be killed by the player (g->u)! g->u.add_memorial_log(pgettext("memorial_male","Killed a %s."), pgettext("memorial_female", "Killed a %s."), z->name().c_str()); } m_size monSize = (z->type->size); bool isFleshy = (z->made_of("flesh") || z->made_of("hflesh")); bool leaveCorpse = !(z->type->has_flag(MF_VERMIN)); // leave some blood if we have to if (isFleshy && z->has_flag(MF_WARM) && !z->has_flag(MF_VERMIN)) { g->m.add_field(z->posx(), z->posy(), fd_blood, 1); } int maxHP = z->type->hp; if (!maxHP) { maxHP = 1; } float overflowDamage = -(z->hp); float corpseDamage = 5 * (overflowDamage / (maxHP * 2)); if (leaveCorpse) { int gibAmount = int(floor(corpseDamage)) - 1; // allow one extra gib per 5 HP int gibLimit = 1 + (maxHP / 5.0); if (gibAmount > gibLimit) { gibAmount = gibLimit; } bool pulverized = (corpseDamage > 5 && overflowDamage > 150); if (!pulverized) { make_mon_corpse(z, int(floor(corpseDamage))); } else if (monSize >= MS_MEDIUM) { gibAmount += rng(1,6); } // Limit chunking to flesh and veggy creatures until other kinds are supported. bool leaveGibs = (isFleshy || z->made_of("veggy")); if (leaveGibs) { make_gibs( z, gibAmount); } } }
void mdeath::normal(monster *z) { if (g->u_see(z)) { add_msg(m_good, _("The %s dies!"), z->name().c_str()); //Currently it is possible to get multiple messages that a monster died. } m_size monSize = (z->type->size); bool leaveCorpse = !(z->type->has_flag(MF_VERMIN)); // leave some blood if we have to if (!z->has_flag(MF_VERMIN)) { field_id type_blood = z->bloodType(); if (type_blood != fd_null) { g->m.add_field(z->posx(), z->posy(), type_blood, 1); } } int maxHP = z->type->hp; if (!maxHP) { maxHP = 1; } float overflowDamage = -(z->hp); float corpseDamage = 5 * (overflowDamage / (maxHP * 2)); if (leaveCorpse) { int gibAmount = int(floor(corpseDamage)) - 1; // allow one extra gib per 5 HP int gibLimit = 1 + (maxHP / 5.0); if (gibAmount > gibLimit) { gibAmount = gibLimit; } bool pulverized = (corpseDamage > 5 && overflowDamage > 150); if (!pulverized) { make_mon_corpse(z, int(floor(corpseDamage))); } else if (monSize >= MS_MEDIUM) { gibAmount += rng(1, 6); } // Limit chunking to flesh, veggy and insect creatures until other kinds are supported. bool leaveGibs = (z->made_of("flesh") || z->made_of("hflesh") || z->made_of("veggy") || z->made_of("iflesh")); if (leaveGibs) { make_gibs( z, gibAmount ); } } }
void mdeath::normal( monster &z ) { if( z.no_corpse_quiet ) { return; } if( z.type->in_species( ZOMBIE ) ) { sfx::play_variant_sound( "mon_death", "zombie_death", sfx::get_heard_volume( z.pos() ) ); } if( g->u.sees( z ) ) { //Currently it is possible to get multiple messages that a monster died. add_msg( m_good, _( "The %s dies!" ), z.name() ); } const int max_hp = std::max( z.get_hp_max(), 1 ); const float overflow_damage = std::max( -z.get_hp(), 0 ); const float corpse_damage = 2.5 * overflow_damage / max_hp; const bool pulverized = corpse_damage > 5 && overflow_damage > z.get_hp_max(); z.bleed(); // leave some blood if we have to if( !pulverized ) { make_mon_corpse( z, static_cast<int>( std::floor( corpse_damage * itype::damage_scale ) ) ); } // if mdeath::splatter was set along normal makes sure it is not called twice bool splatt = false; for( const auto &deathfunction : z.type->dies ) { if( deathfunction == mdeath::splatter ) { splatt = true; } } if( !splatt ) { splatter( z ); } }
void mdeath::normal( monster &z ) { if( z.no_corpse_quiet ) { return; } if( z.type->in_species( ZOMBIE ) ) { sfx::play_variant_sound( "mon_death", "zombie_death", sfx::get_heard_volume( z.pos() ) ); } if( g->u.sees( z ) ) { //Currently it is possible to get multiple messages that a monster died. add_msg( m_good, _( "The %s dies!" ), z.name().c_str() ); } const int max_hp = std::max( z.get_hp_max(), 1 ); const float overflow_damage = std::max( -z.get_hp(), 0 ); const float corpse_damage = 2.5 * overflow_damage / max_hp; const bool pulverized = corpse_damage > 5 && overflow_damage > z.get_hp_max(); z.bleed(); // leave some blood if we have to if( !pulverized ) { make_mon_corpse( z, int( std::floor( corpse_damage ) ) ); } // Limit chunking to flesh, veggy and insect creatures until other kinds are supported. const std::vector<material_id> gib_mats = {{ material_id( "flesh" ), material_id( "hflesh" ), material_id( "veggy" ), material_id( "iflesh" ), material_id( "bone" ) }}; const bool gibbable = !z.type->has_flag( MF_NOGIB ) && std::any_of( gib_mats.begin(), gib_mats.end(), [&z]( const material_id &gm ) { return z.made_of( gm ); } ); const field_id type_blood = z.bloodType(); const field_id type_gib = z.gibType(); if( gibbable ) { const auto area = g->m.points_in_radius( z.pos(), 1 ); int number_of_gibs = std::min( std::floor( corpse_damage ) - 1, 1 + max_hp / 5.0f ); if( pulverized && z.type->size >= MS_MEDIUM ) { number_of_gibs += rng( 1, 6 ); sfx::play_variant_sound( "mon_death", "zombie_gibbed", sfx::get_heard_volume( z.pos() ) ); } for( int i = 0; i < number_of_gibs; ++i ) { g->m.add_splatter( type_gib, random_entry( area ), rng( 1, i + 1 ) ); g->m.add_splatter( type_blood, random_entry( area ) ); } } const int num_chunks = z.type->get_meat_chunks_count(); if( pulverized && gibbable ) { const itype_id meat = z.type->get_meat_itype(); const item chunk( meat ); for( int i = 0; i < num_chunks; i++ ) { tripoint tarp( z.pos() + point( rng( -3, 3 ), rng( -3, 3 ) ) ); const auto traj = line_to( z.pos(), tarp ); for( size_t j = 0; j < traj.size(); j++ ) { tarp = traj[j]; if( one_in( 2 ) && type_blood != fd_null ) { g->m.add_splatter( type_blood, tarp ); } else { g->m.add_splatter( type_gib, tarp, rng( 1, j + 1 ) ); } if( g->m.impassable( tarp ) ) { g->m.bash( tarp, 3 ); if( g->m.impassable( tarp ) ) { // Target is obstacle, not destroyed by bashing, // stop trajectory in front of it, if this is the first // point (e.g. wall adjacent to monster) , make it invalid. if( j > 0 ) { tarp = traj[j - 1]; } else { tarp = tripoint_min; } break; } } } if( tarp != tripoint_min ) { g->m.add_item_or_charges( tarp, chunk ); } } } }