void monster::apply_damage(Creature* source, body_part /*bp*/, int dam) { if( is_dead_state() ) { return; } hp -= dam; if( hp < 1 ) { set_killer( source ); } else if( dam > 0 ) { process_trigger( MTRIG_HURT, 1 + int( dam / 3 ) ); } }
// Actual player death is mostly handled in game::is_game_over void Character::die(Creature* nkiller) { set_killer( nkiller ); set_turn_died(int(calendar::turn)); if( has_effect( "lightsnare" ) ) { inv.add_item( item( "string_36", 0 ) ); inv.add_item( item( "snare_trigger", 0 ) ); } if( has_effect( "heavysnare" ) ) { inv.add_item( item( "rope_6", 0 ) ); inv.add_item( item( "snare_trigger", 0 ) ); } if( has_effect( "beartrap" ) ) { inv.add_item( item( "beartrap", 0 ) ); } }
// Actual player death is mostly handled in game::is_game_over void Character::die(Creature* nkiller) { set_killer( nkiller ); set_turn_died(int(calendar::turn)); if( has_effect( effect_lightsnare ) ) { inv.add_item( item( "string_36", 0 ) ); inv.add_item( item( "snare_trigger", 0 ) ); } if( has_effect( effect_heavysnare ) ) { inv.add_item( item( "rope_6", 0 ) ); inv.add_item( item( "snare_trigger", 0 ) ); } if( has_effect( effect_beartrap ) ) { inv.add_item( item( "beartrap", 0 ) ); } mission::on_creature_death( *this ); }
void monster::die(Creature* nkiller) { if( dead ) { // We are already dead, don't die again, note that monster::dead is // *only* set to true in this function! return; } dead = true; set_killer( nkiller ); if( hp < -( type->size < MS_MEDIUM ? 1.5 : 3 ) * type->hp ) { explode(); // Explode them if it was big overkill } if (!no_extra_death_drops) { drop_items_on_death(); } // TODO: should actually be class Character player *ch = dynamic_cast<player*>( get_killer() ); if( !is_hallucination() && ch != nullptr ) { if( has_flag( MF_GUILT ) || ( ch->has_trait( "PACIFIST" ) && has_flag( MF_HUMAN ) ) ) { // has guilt flag or player is pacifist && monster is humanoid mdeath::guilt(this); } // TODO: add a kill counter to npcs? if( ch->is_player() ) { g->increase_kill_count( type->id ); } if( type->difficulty >= 30 ) { ch->add_memorial_log( pgettext( "memorial_male", "Killed a %s." ), pgettext( "memorial_female", "Killed a %s." ), name().c_str() ); } } // We were tied up at the moment of death, add a short rope to inventory if ( has_effect("tied") ) { item rope_6("rope_6", 0); add_item(rope_6); } if( !is_hallucination() ) { for( const auto &it : inv ) { g->m.add_item_or_charges( posx(), posy(), it ); } } // If we're a queen, make nearby groups of our type start to die out if( !is_hallucination() && has_flag( MF_QUEEN ) ) { // The submap coordinates of this monster, monster groups coordinates are // submap coordinates. const point abssub = overmapbuffer::ms_to_sm_copy( g->m.getabs( posx(), posy() ) ); // Do it for overmap above/below too for( int z = 1; z >= -1; --z ) { for( int x = -MAPSIZE / 2; x <= MAPSIZE / 2; x++ ) { for( int y = -MAPSIZE / 2; y <= MAPSIZE / 2; y++ ) { std::vector<mongroup*> groups = overmap_buffer.groups_at( abssub.x + x, abssub.y + y, g->levz + z ); for( auto &mgp : groups ) { if( MonsterGroupManager::IsMonsterInGroup( mgp->type, type->id ) ) { mgp->dying = true; } } } } } } // If we're a mission monster, update the mission if (!is_hallucination() && mission_id != -1) { mission_type *misstype = g->find_mission_type(mission_id); if (misstype->goal == MGOAL_FIND_MONSTER) { g->fail_mission(mission_id); } if (misstype->goal == MGOAL_KILL_MONSTER) { g->mission_step_complete(mission_id, 1); } } // Also, perform our death function if(is_hallucination()) { //Hallucinations always just disappear mdeath::disappear(this); return; } //Not a hallucination, go process the death effects. for (auto const &deathfunction : type->dies) { deathfunction(this); } // If our species fears seeing one of our own die, process that int anger_adjust = 0, morale_adjust = 0; if (type->has_anger_trigger(MTRIG_FRIEND_DIED)){ anger_adjust += 15; } if (type->has_fear_trigger(MTRIG_FRIEND_DIED)){ morale_adjust -= 15; } if (type->has_placate_trigger(MTRIG_FRIEND_DIED)){ anger_adjust -= 15; } if (anger_adjust != 0 || morale_adjust != 0) { int light = g->light_level(); for (size_t i = 0; i < g->num_zombies(); i++) { monster &critter = g->zombie( i ); if( !critter.type->same_species( *type ) ) { continue; } int t = 0; if( g->m.sees( critter.pos(), pos(), light, t ) ) { critter.morale += morale_adjust; critter.anger += anger_adjust; } } } }
// Actual player death is mostly handled in game::is_game_over void Character::die(Creature* nkiller) { set_killer( nkiller ); set_turn_died(int(calendar::turn)); }