diff options
author | megamage <none@none> | 2009-01-09 16:43:23 -0600 |
---|---|---|
committer | megamage <none@none> | 2009-01-09 16:43:23 -0600 |
commit | 1ffb1cef3344206dfea149cb78146c30449d51c2 (patch) | |
tree | 655ac591f6f5aaca3dc65d67f3940f589e2394db /src/game/Unit.cpp | |
parent | 5c8f52d134899e10484dd47e91b612e2228842bf (diff) | |
parent | 90a82a81ad5d20d5e7188d6e9d660280f0b1eab4 (diff) |
*Merge.
--HG--
branch : trunk
Diffstat (limited to 'src/game/Unit.cpp')
-rw-r--r-- | src/game/Unit.cpp | 332 |
1 files changed, 260 insertions, 72 deletions
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 2c3432abb57..535465d52d2 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -158,7 +158,6 @@ Unit::Unit() m_removedAuras = 0; m_charmInfo = NULL; m_unit_movement_flags = 0; - m_isPossessed = false; m_reducedThreatPercent = 0; m_misdirectionTargetGUID = 0; @@ -567,7 +566,7 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa CreatureInfo const* cInfo = ((Creature*)pVictim)->GetCreatureInfo(); if(cInfo && cInfo->lootid) - pVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pVictim->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); // some critters required for quests if(GetTypeId() == TYPEID_PLAYER) @@ -1160,17 +1159,14 @@ uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType) { - SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask); - Unit *pVictim = damageInfo->target; - if (damage < 0) return; - if(!this || !pVictim) - return; - if(!this->isAlive() || !pVictim->isAlive()) + Unit *pVictim = damageInfo->target; + if(!pVictim || !pVictim->isAlive()) return; + SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask); uint32 crTypeMask = pVictim->GetCreatureTypeMask(); // Check spell crit chance bool crit = isSpellCrit(pVictim, spellInfo, damageSchoolMask, attackType); @@ -1185,17 +1181,10 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 dama // Physical Damage if ( damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL ) { - //Calculate armor mitigation - //damage = CalcArmorReducedDamage(pVictim, damage); // Get blocked status blocked = isSpellBlocked(pVictim, spellInfo, attackType); } - // Magical Damage - /*else - { - // Calculate damage bonus - damage = SpellDamageBonus(pVictim, spellInfo, damage, SPELL_DIRECT_DAMAGE); - }*/ + if (crit) { damageInfo->HitInfo|= SPELL_HIT_TYPE_CRIT; @@ -1240,8 +1229,6 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 dama case SPELL_DAMAGE_CLASS_NONE: case SPELL_DAMAGE_CLASS_MAGIC: { - // Calculate damage bonus - //damage = SpellDamageBonus(pVictim, spellInfo, damage, SPELL_DIRECT_DAMAGE); // If crit add critical bonus if (crit) { @@ -7038,10 +7025,11 @@ void Unit::SetPet(Pet* pet) void Unit::SetCharm(Unit* pet) { - SetUInt64Value(UNIT_FIELD_CHARM, pet ? pet->GetGUID() : 0); - if(GetTypeId() == TYPEID_PLAYER) + { + SetUInt64Value(UNIT_FIELD_CHARM, pet ? pet->GetGUID() : 0); ((Player*)this)->m_mover = pet ? pet : this; + } } void Unit::AddPlayerToVision(Player* plr) @@ -7084,21 +7072,6 @@ void Unit::UncharmSelf() RemoveSpellsCausingAura(SPELL_AURA_MOD_CHARM); } -void Unit::UnpossessSelf(bool attack) -{ - if (!isPossessed() || !GetCharmer()) - return; - - if (GetCharmer()->GetTypeId() == TYPEID_PLAYER) - ((Player*)GetCharmer())->RemovePossess(attack); - else - { - GetCharmer()->SetCharm(0); - SetCharmerGUID(0); - m_isPossessed = false; - } -} - void Unit::UnsummonAllTotems() { for (int8 i = 0; i < MAX_TOTEM; ++i) @@ -7142,8 +7115,8 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 if(!spellProto || !pVictim || damagetype==DIRECT_DAMAGE ) return pdamage; - if(spellProto->SchoolMask == SPELL_SCHOOL_MASK_NORMAL) - return pdamage; + //if(spellProto->SchoolMask == SPELL_SCHOOL_MASK_NORMAL) + // return pdamage; //damage = CalcArmorReducedDamage(pVictim, damage); int32 BonusDamage = 0; @@ -7521,7 +7494,9 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 // Spellmod SpellDamage //float SpellModSpellDamage = 100.0f; - float CoefficientPtc = ((float)CastingTime/3500.0f)*DotFactor*100.0f; + float CoefficientPtc = DotFactor * 100.0f; + if(spellProto->SchoolMask != SPELL_SCHOOL_MASK_NORMAL) + CoefficientPtc *= ((float)CastingTime/3500.0f); if(Player* modOwner = GetSpellModOwner()) //modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,SpellModSpellDamage); @@ -7531,10 +7506,11 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 CoefficientPtc /= 100.0f; //float DoneActualBenefit = DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * SpellModSpellDamage * LvlPenalty; + float DoneActualBenefit = DoneAdvertisedBenefit * CoefficientPtc * LvlPenalty; - float TakenActualBenefit = TakenAdvertisedBenefit; - if(spellProto->SpellFamilyName) - TakenActualBenefit *= (CastingTime / 3500.0f) * DotFactor * LvlPenalty; + float TakenActualBenefit = TakenAdvertisedBenefit * DotFactor * LvlPenalty; + if(spellProto->SpellFamilyName && spellProto->SchoolMask != SPELL_SCHOOL_MASK_NORMAL) + TakenActualBenefit *= ((float)CastingTime / 3500.0f); float tmpDamage = (float(pdamage)+DoneActualBenefit)*DoneTotalMod; @@ -8642,6 +8618,24 @@ bool Unit::canDetectStealthOf(Unit const* target, float distance) const return distance < visibleDistance; } +void Unit::DestroyForNearbyPlayers() +{ + if(!IsInWorld()) + return; + + std::list<Unit*> targets; + Trinity::AnyUnitInObjectRangeCheck check(this, World::GetMaxVisibleDistance()); + Trinity::UnitListSearcher<Trinity::AnyUnitInObjectRangeCheck> searcher(targets, check); + VisitNearbyWorldObject(World::GetMaxVisibleDistance(), searcher); + for(std::list<Unit*>::iterator iter = targets.begin(); iter != targets.end(); ++iter) + if(*iter != this && (*iter)->GetTypeId() == TYPEID_PLAYER + && ((Player*)(*iter))->HaveAtClient(this)) + { + DestroyForPlayer((Player*)(*iter)); + ((Player*)(*iter))->m_clientGUIDs.erase(GetGUID()); + } +} + void Unit::SetVisibility(UnitVisibility x) { m_Visibility = x; @@ -8650,27 +8644,7 @@ void Unit::SetVisibility(UnitVisibility x) SetToNotify(); if(x == VISIBILITY_GROUP_STEALTH) - { - std::list<Unit*> targets; - Trinity::AnyUnitInObjectRangeCheck check(this, World::GetMaxVisibleDistance()); - Trinity::UnitListSearcher<Trinity::AnyUnitInObjectRangeCheck> searcher(targets, check); - VisitNearbyWorldObject(World::GetMaxVisibleDistance(), searcher); - for(std::list<Unit*>::iterator iter = targets.begin(); iter != targets.end(); ++iter) - if(*iter != this && (*iter)->GetTypeId() == TYPEID_PLAYER - && ((Player*)(*iter))->HaveAtClient(this)) - { - DestroyForPlayer((Player*)(*iter)); - ((Player*)(*iter))->m_clientGUIDs.erase(GetGUID()); - } - } - /*{ - Map *m = GetMap(); - - if(GetTypeId()==TYPEID_PLAYER) - m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); - else - m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); - }*/ + DestroyForNearbyPlayers(); } void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) @@ -8905,7 +8879,7 @@ void Unit::setDeathState(DeathState s) UnsummonAllTotems(); // Possessed unit died, restore control to possessor - UnpossessSelf(false); + RemoveCharmedOrPossessedBy(NULL); RemoveAllFromVision(); ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); @@ -9779,7 +9753,7 @@ void Unit::CleanupsBeforeDelete() { if(m_uint32Values) // only for fully created object { - UnpossessSelf(false); + RemoveCharmedOrPossessedBy(NULL); RemoveAllFromVision(); InterruptNonMeleeSpells(true); m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList @@ -11439,22 +11413,236 @@ void Unit::SetConfused(bool apply) ((Player*)this)->SetClientControl(this, !apply); } +void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess) +{ + if(!charmer) + return; + + assert(!possess || charmer->GetTypeId() == TYPEID_PLAYER); + + if(this == charmer) + return; + + if(isInFlight()) + return; + + if(GetTypeId() == TYPEID_PLAYER && ((Player*)this)->GetTransport()) + return; + + RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + CastStop(); + CombatStop(); //TODO: CombatStop(true) may cause crash (interrupt spells) + DeleteThreatList(); + + // Charmer stop charming + if(charmer->GetTypeId() == TYPEID_PLAYER) + ((Player*)charmer)->StopCharmOrPossess(); + + // Charmed stop charming + if(GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->StopCharmOrPossess(); + + // Charmed stop being charmed + RemoveCharmedOrPossessedBy(NULL); + + // Set charmed + charmer->SetCharm(this); + SetCharmerGUID(charmer->GetGUID()); + setFaction(charmer->getFaction()); + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + + if(GetTypeId() == TYPEID_UNIT) + { + ((Creature*)this)->InitPossessedAI(); + StopMoving(); + GetMotionMaster()->Clear(false); + GetMotionMaster()->MoveIdle(); + } + else + { + if(((Player*)this)->isAFK()) + ((Player*)this)->ToggleAFK(); + ((Player*)this)->SetViewport(GetGUID(), false); + } + + // Pets already have a properly initialized CharmInfo, don't overwrite it. + if(GetTypeId() == TYPEID_PLAYER || GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet()) + { + CharmInfo *charmInfo = InitCharmInfo(this); + charmInfo->SetReactState(REACT_DEFENSIVE); + if(possess) + charmInfo->InitPossessCreateSpells(); + else + charmInfo->InitCharmCreateSpells(); + } + + //Set possessed + if(possess) + { + addUnitState(UNIT_STAT_POSSESSED); + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + AddPlayerToVision((Player*)charmer); + ((Player*)charmer)->SetViewport(GetGUID(), true); + charmer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + } + // Charm demon + else if(GetTypeId() == TYPEID_UNIT && charmer->GetTypeId() == TYPEID_PLAYER && charmer->getClass() == CLASS_WARLOCK) + { + CreatureInfo const *cinfo = ((Creature*)this)->GetCreatureInfo(); + if(cinfo && cinfo->type == CREATURE_TYPE_DEMON) + { + //to prevent client crash + SetFlag(UNIT_FIELD_BYTES_0, 2048); + + //just to enable stat window + if(GetCharmInfo()) + GetCharmInfo()->SetPetNumber(objmgr.GeneratePetNumber(), true); + + //if charmed two demons the same session, the 2nd gets the 1st one's name + SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); + } + } + + if(possess) + ((Player*)charmer)->PossessSpellInitialize(); + else if(charmer->GetTypeId() == TYPEID_PLAYER) + ((Player*)charmer)->CharmSpellInitialize(); +} + +void Unit::RemoveCharmedOrPossessedBy(Unit *charmer) +{ + if(!isCharmed()) + return; + + if(!charmer) + charmer = GetCharmer(); + else if(charmer != GetCharmer()) // one aura overrides another? + return; + + bool possess = hasUnitState(UNIT_STAT_POSSESSED); + + CastStop(); + CombatStop(); //TODO: CombatStop(true) may cause crash (interrupt spells) + getHostilRefManager().deleteReferences(); + DeleteThreatList(); + SetCharmerGUID(0); + RestoreFaction(); + + if(possess) + { + clearUnitState(UNIT_STAT_POSSESSED); + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + } + + if(GetTypeId() == TYPEID_UNIT) + { + if(!((Creature*)this)->isPet()) + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + + ((Creature*)this)->DisablePossessedAI(); + if(isAlive() && ((Creature*)this)->AI()) + { + if(charmer && !IsFriendlyTo(charmer)) + { + ((Creature*)this)->AddThreat(charmer, 10000.0f); + ((Creature*)this)->AI()->AttackStart(charmer); + } + else + ((Creature*)this)->AI()->EnterEvadeMode(); + } + } + else + ((Player*)this)->SetViewport(GetGUID(), true); + + // If charmer still exists + if(!charmer) + return; + + assert(!possess || charmer->GetTypeId() == TYPEID_PLAYER); + + charmer->SetCharm(0); + if(possess) + { + RemovePlayerFromVision((Player*)charmer); + ((Player*)charmer)->SetViewport(charmer->GetGUID(), true); + charmer->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + } + // restore UNIT_FIELD_BYTES_0 + else if(GetTypeId() == TYPEID_UNIT && charmer->GetTypeId() == TYPEID_PLAYER && charmer->getClass() == CLASS_WARLOCK) + { + CreatureInfo const *cinfo = ((Creature*)this)->GetCreatureInfo(); + if(cinfo && cinfo->type == CREATURE_TYPE_DEMON) + { + CreatureDataAddon const *cainfo = ((Creature*)this)->GetCreatureAddon(); + if(cainfo && cainfo->bytes0 != 0) + SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0); + else + RemoveFlag(UNIT_FIELD_BYTES_0, 2048); + + if(GetCharmInfo()) + GetCharmInfo()->SetPetNumber(0, true); + else + sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", GetGUID(), GetTypeId()); + } + } + + if(possess || charmer->GetTypeId() == TYPEID_PLAYER) + { + // Remove pet spell action bar + WorldPacket data(SMSG_PET_SPELLS, 8); + data << uint64(0); + ((Player*)charmer)->GetSession()->SendPacket(&data); + } +} + +void Unit::RestoreFaction() +{ + if(GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->setFactionForRace(getRace()); + else + { + CreatureInfo const *cinfo = ((Creature*)this)->GetCreatureInfo(); + + if(((Creature*)this)->isPet()) + { + if(Unit* owner = GetOwner()) + setFaction(owner->getFaction()); + else if(cinfo) + setFaction(cinfo->faction_A); + } + else if(cinfo) // normal creature + setFaction(cinfo->faction_A); + } +} + bool Unit::IsInPartyWith(Unit const *unit) const { - const Player *p1 = GetCharmerOrOwnerPlayerOrPlayerItself(); - const Player *p2 = unit->GetCharmerOrOwnerPlayerOrPlayerItself(); - if(p1 && p2) - return p1->IsInSameGroupWith(p2); + if(this == unit) + return true; + + const Unit *u1 = GetCharmerOrOwnerOrSelf(); + const Unit *u2 = unit->GetCharmerOrOwnerOrSelf(); + if(u1 == u2) + return true; + + if(u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_PLAYER) + return ((Player*)u1)->IsInSameGroupWith((Player*)u2); else return false; } bool Unit::IsInRaidWith(Unit const *unit) const { - const Player *p1 = GetCharmerOrOwnerPlayerOrPlayerItself(); - const Player *p2 = unit->GetCharmerOrOwnerPlayerOrPlayerItself(); - if(p1 && p2) - return p1->IsInSameRaidWith(p2); + if(this == unit) + return true; + + const Unit *u1 = GetCharmerOrOwnerOrSelf(); + const Unit *u2 = unit->GetCharmerOrOwnerOrSelf(); + if(u1 == u2) + return true; + + if(u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_PLAYER) + return ((Player*)u1)->IsInSameRaidWith((Player*)u2); else return false; } |