DeathList Creature::getKillers() { DeathList list; CountMap::const_iterator it; Creature* lhc = NULL; if((lhc = g_game.getCreatureByID(lastHitCreature))) { int32_t damage = 0; if((it = damageMap.find(lastHitCreature)) != damageMap.end()) damage = it->second.total; list.push_back(DeathEntry(lhc, damage)); } else list.push_back(DeathEntry(getCombatName(lastDamageSource), 0)); int32_t requiredTime = g_config.getNumber(ConfigManager::DEATHLIST_REQUIRED_TIME); int64_t now = OTSYS_TIME(); CountBlock_t cb; for(it = damageMap.begin(); it != damageMap.end(); ++it) { cb = it->second; if((now - cb.ticks) > requiredTime) continue; Creature* mdc = g_game.getCreatureByID(it->first); if(!mdc || mdc == lhc || (lhc && (mdc->getMaster() == lhc || lhc->getMaster() == mdc))) continue; bool deny = false; for(DeathList::iterator fit = list.begin(); fit != list.end(); ++fit) { if(fit->isNameKill()) continue; Creature* tmp = fit->getKillerCreature(); if(!(mdc->getName() == tmp->getName() && mdc->getMaster() == tmp->getMaster()) && (!mdc->getMaster() || (mdc->getMaster() != tmp && mdc->getMaster() != tmp->getMaster())) && (mdc->getSummonCount() <= 0 || tmp->getMaster() != mdc)) continue; deny = true; break; } if(!deny) list.push_back(DeathEntry(mdc, cb.total)); } if(list.size() > 1) std::sort(list.begin() + 1, list.end(), DeathLessThan()); return list; }
bool Creature::onDeath() { DeathList deathList = getKillers(); bool deny = false; CreatureEventList prepareDeathEvents = getCreatureEvents(CREATURE_EVENT_PREPAREDEATH); for(CreatureEventList::iterator it = prepareDeathEvents.begin(); it != prepareDeathEvents.end(); ++it) { if(!(*it)->executePrepareDeath(this, deathList) && !deny) deny = true; } if(deny) return false; int32_t i = 0, size = deathList.size(), limit = g_config.getNumber(ConfigManager::DEATH_ASSISTS) + 1; if(limit > 0 && size > limit) size = limit; Creature* tmp = NULL; CreatureVector justifyVec; for(DeathList::iterator it = deathList.begin(); it != deathList.end(); ++it, ++i) { if(it->isNameKill()) continue; if(it == deathList.begin()) it->setLast(); if(i < size) { if(it->getKillerCreature()->getPlayer()) tmp = it->getKillerCreature(); else if(it->getKillerCreature()->getPlayerMaster()) tmp = it->getKillerCreature()->getMaster(); } if(tmp) { if(std::find(justifyVec.begin(), justifyVec.end(), tmp) == justifyVec.end()) { it->setJustify(); justifyVec.push_back(tmp); } tmp = NULL; } if(!it->getKillerCreature()->onKilledCreature(this, (*it)) && it->isLast()) return false; } for(CountMap::iterator it = damageMap.begin(); it != damageMap.end(); ++it) { if((tmp = g_game.getCreatureByID(it->first))) tmp->onTargetKilled(this); } dropCorpse(deathList); if(master) master->removeSummon(this); return true; }