void monster::die() { if (!dead) dead = true; if (!no_extra_death_drops) { drop_items_on_death(); } if (type->difficulty >= 30 && get_killer() != NULL && get_killer()->is_player()) { g->u.add_memorial_log( pgettext("memorial_male", "Killed a %s."), pgettext("memorial_female", "Killed a %s."), name().c_str()); } // If we're a queen, make nearby groups of our type start to die out if (has_flag(MF_QUEEN)) { // Do it for overmap above/below too for(int z = 0; 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 = g->cur_om->monsters_at(g->levx+x, g->levy+y, z); for (int i = 0; i < groups.size(); i++) { if (MonsterGroupManager::IsMonsterInGroup (groups[i]->type, (type->id))) groups[i]->dying = true; } } } } } // If we're a mission monster, update the mission if (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 mdeath md; if(is_hallucination()) { //Hallucinations always just disappear md.disappear(this); return; } else { //Not a hallucination, go process the death effects. std::vector<void (mdeath::*)(monster *)> deathfunctions = type->dies; void (mdeath::*func)(monster *); for (int i = 0; i < deathfunctions.size(); i++) { func = deathfunctions.at(i); (md.*func)(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 (int i = 0; i < g->num_zombies(); i++) { int t = 0; if (g->m.sees(g->zombie(i).posx(), g->zombie(i).posy(), _posx, _posy, light, t)) { g->zombie(i).morale += morale_adjust; g->zombie(i).anger += anger_adjust; } } } }
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; if( nkiller != NULL && !nkiller->is_fake() ) { 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 tmpdeath; tmpdeath.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() ); } } 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( 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 (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 mdeath md; if(is_hallucination()) { //Hallucinations always just disappear md.disappear(this); return; } else { //Not a hallucination, go process the death effects. std::vector<void (mdeath::*)(monster *)> deathfunctions = type->dies; void (mdeath::*func)(monster *); for (size_t i = 0; i < deathfunctions.size(); i++) { func = deathfunctions.at(i); (md.*func)(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.posx(), critter.posy(), _posx, _posy, light, t ) ) { critter.morale += morale_adjust; critter.anger += anger_adjust; } } } }