int DamageOverTimeList::getStrength(uint8 pool, uint64 dotType) { Locker locker(&guard); Vector<DamageOverTime>* vector; int strength = 0; for(int i = 0; i < size(); i++) { vector = &elementAt(i).getValue(); for(int j = 0; j < vector->size(); j++) { DamageOverTime* currentDot = &vector->elementAt(j); if(currentDot->getType() == dotType && (currentDot->getAttribute() == pool || pool == 0xFF)) { if (!currentDot->isPast()) { strength+=currentDot->getStrength(); } } } } return strength; }
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; }