Exemple #1
0
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;
}
Exemple #2
0
DeathList Creature::getKillers(int32_t assist_count /*= 1*/)
{
	DeathList list;
	Creature* lhc = g_game.getCreatureByID(lastHitCreature);
	if(lhc){
		list.push_back(DeathEntry(lhc, 0, Combat::isUnjustKill(lhc, this))); // Final Hit killer
	}
	else{
		list.push_back(DeathEntry(combatTypeToString(lastDamageSource), 0));
	}

	if(assist_count == 0){
		return list;
	}
	else if(assist_count == 1){
		// Optimized case for last hit + one killer
		Creature* mdc = NULL;
		int32_t mostDamage = 0;
		int64_t now = OTSYS_TIME();

		for(CountMap::const_iterator it = damageMap.begin(); it != damageMap.end(); ++it){
			const CountBlock_t& cb = it->second;
			if(cb.total > mostDamage && (now - cb.ticks <= g_game.getInFightTicks())){
				Creature* tmpDamageCreature = g_game.getCreatureByID(it->first);
				if(tmpDamageCreature){
					mdc = tmpDamageCreature;
					mostDamage = cb.total;
				}
			}
		}

		if(mdc && mdc != lhc){
			if(lhc && (mdc->getMaster() == lhc || lhc->getMaster() == mdc || (lhc->getMaster() && lhc->getMaster() == mdc->getMaster()))){
				return list;
			}
			else{
				list.push_back(DeathEntry(mdc, mostDamage, Combat::isUnjustKill(mdc, this)));
			}
		}
	}
	else{
		int64_t now = OTSYS_TIME();

		// Add all (recent) damagers to the list
		for(CountMap::const_iterator it = damageMap.begin(); it != damageMap.end(); ++it){
			const CountBlock_t& cb = it->second;
			if(now - cb.ticks <= g_game.getInFightTicks()){
				Creature* mdc = g_game.getCreatureByID(it->first);
				// Player who made last hit is not included in assist list
				if(mdc && mdc != lhc){
					// Check if master is last hit creature, or if our summon is last hit creature
					if(lhc && (mdc->getMaster() == lhc || lhc->getMaster() == mdc)){
						continue;
					}

					// Check if master has already been added to the list
					if(mdc->getMaster()){
						bool cont = false;
						for(DeathList::iterator finder = list.begin(); finder != list.end(); ++finder){
							if(finder->isCreatureKill()){
								Creature* c = finder->getKillerCreature();
								if(mdc->getMaster() == c || mdc->getMaster() == c->getMaster()){
									cont = true;
									break;
								}
							}
						}
						if(cont){
							continue;
						}
					}

					// Check if our summon has already been added to the list
					if(mdc->getSummonCount() > 0){
						bool cont = false;
						for(DeathList::iterator finder = list.begin(); finder != list.end(); ++finder){
							if(finder->isCreatureKill()){
								Creature* c = finder->getKillerCreature();
								if(c->getMaster() == mdc){
									cont = true;
									break;
								}
							}
						}
						if(cont){
							continue;
						}
					}

					list.push_back(DeathEntry(mdc, cb.total, Combat::isUnjustKill(mdc, this)));
				}
			}
		}
		// Sort them by damage, first is always final hit killer
		if(list.size() > 1){
			std::sort(list.begin() + 1, list.end(), DeathLessThan());
		}
	}

	if(list.size() > (uint32_t)assist_count + 1){
		// Shrink list to assist_count
		list.resize(assist_count + 1, DeathEntry("", -1));
	}

	return list;
}
Exemple #3
0
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;
}