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;
   }
  }
 }
}
Example #2
0
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;
            }
        }
    }
}