Пример #1
0
BigDotList::BigDotList(Leap::Image &img) : bigDots()
{
	value = 0;
	const unsigned char *imgData = img.data();
	for (int i = 0; i < img.width()*img.height(); i++) {
		if (imgData[i] < Dot::thres)
			continue;
		int y = i/img.width();
		Dot newDot(Coord(i-y, y));
		bool groupFound = true;
		/* Check if dot belongs to another group */
		std::vector<BigDot> bd;
		std::vector<Dot> d;
		for (std::vector<BigDot>::iterator bd = bigDots.begin();
		    bd != bigDots.end(); ++bd) {
			for (std::vector<Dot>::iterator d = bd->dots.begin();
			     d != bd->dots.begin(); ++d) {
				if (newDot.pos.getDist(d->pos) < Dot::r) {
					bd->add(newDot);
					groupFound = true;
					break;
				}
			}
			if (groupFound) break;
		}
	}
}
uint32 DamageOverTimeList::addDot(CreatureObject* victim,
								  CreatureObject* attacker,
								  uint64 objectID,
								  uint32 duration,
								  uint64 dotType,
								  uint8 pool,
								  uint32 strength,
								  float potency,
								  uint32 defense,
								  int secondaryStrength) {
	Locker locker(&guard);

	if (strength == 0 || duration == 0)
		return 0;

	// determine chance to hit, if no hit, just return 0. potency of less than 0 can't be resisted
	if (potency > 0 && System::random(100) >= MAX(5.f, MIN(potency * (80.f / (100.f + defense)), 95.f)))
		return 0;

	if (pool == CreatureAttribute::UNKNOWN) {
		pool = getRandomPool(dotType);
	}

	int oldStrength = getStrength(pool, dotType);

	int durationMod = 0;

	switch (dotType) {
	case CreatureState::POISONED:
		durationMod = victim->getSkillMod("dissipation_poison");
		break;
	case CreatureState::DISEASED:
		durationMod = victim->getSkillMod("dissipation_disease");
		break;
	case CreatureState::ONFIRE:
		durationMod = victim->getSkillMod("dissipation_fire");
		break;
	case CreatureState::BLEEDING:
		durationMod = victim->getSkillMod("dissipation_bleeding");
		break;
	default:
		break;
	}

	if (durationMod > 0) {
		if (durationMod > 90) durationMod = 90;
		duration = MAX(1, (int)(duration * (1.f - (durationMod / 100.f))));
	}

	//only 1 disease per bar allowed
	if(dotType == CreatureState::DISEASED) {
		objectID = Long::hashCode(CreatureState::DISEASED);
	} else if (dotType == CommandEffect::FORCECHOKE) {
		objectID = 0;
	}

	DamageOverTime newDot(attacker, dotType, pool, strength, duration, secondaryStrength);
	int dotPower = newDot.initDot(victim, attacker);

	uint64 key = generateKey(dotType, pool, objectID);

	if (contains(key)) {
		Vector<DamageOverTime>* vector = &get(key);
		Vector<DamageOverTime> newVec;

		// This seems to only ever put one value in the DOT vector. This needs to remain a vector to
		// maintain the integrity of the db.
		for (int i = 0; i < vector->size(); ++i) {
			DamageOverTime dot = vector->get(i);

			// Curing the dot can cause the dot to expire but not get
			// removed from the list, so if the dot is expired make sure
			// to not reset it
			if (dot.isPast()) {
				newVec.add(newDot);
			} else if (newDot.getStrength() >= dot.getStrength()) {
				// but we only want to reuse the tick if the old dot has not
				// expired yet but is being replaced due to strength
				newDot.setNextTick(dot.getNextTick());
				newVec.add(newDot);
			} else // the new dot has less strength and the old dot hasn't expired
				newVec.add(dot);

			drop(key);
			put(key, newVec);
		}
	} else {
		Vector<DamageOverTime> newVector;
		newVector.add(newDot);
		put(key, newVector);
	}

	Time nTime = newDot.getNextTick();

	if (isEmpty() || nextTick.isPast() || nTime.compareTo(nextTick) > 0)
		nextTick = nTime;

	if(oldStrength == 0)
		sendStartMessage(victim, dotType);
	else
		sendIncreaseMessage(victim, dotType);

	dot = true;

	locker.release();

	if (dotType != CommandEffect::FORCECHOKE)
		victim->setState(dotType);

	return dotPower;
}