--HG--
branch : trunk
This commit is contained in:
megamage
2009-01-09 16:43:23 -06:00
66 changed files with 1270 additions and 621 deletions
+7 -7
View File
@@ -316,9 +316,9 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
break;
Group *group = GetPlayer()->GetGroup();
if(!group || !group->isRaidGroup())
if(!group || !group->isRaidGroup() || group->isBGGroup())
return;
WorldPacket data;
ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(),NULL);
group->BroadcastPacket(&data);
@@ -342,7 +342,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
break;
Group *group = GetPlayer()->GetGroup();
if(!group || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID()))
if(!group || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID()) || group->isBGGroup())
return;
WorldPacket data;
@@ -362,7 +362,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
break;
Group *group = GetPlayer()->GetGroup();
if(!group || !group->isRaidGroup() || !(group->IsLeader(GetPlayer()->GetGUID()) || group->IsAssistant(GetPlayer()->GetGUID())))
if(!group || !group->isRaidGroup() || !(group->IsLeader(GetPlayer()->GetGUID()) || group->IsAssistant(GetPlayer()->GetGUID())) || group->isBGGroup())
return;
WorldPacket data;
@@ -383,7 +383,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
break;
Group *group = GetPlayer()->GetGroup();
if(!group || !group->isRaidGroup())
if(!group || !group->isRaidGroup() || !group->isBGGroup())
return;
WorldPacket data;
@@ -404,7 +404,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
break;
Group *group = GetPlayer()->GetGroup();
if(!group || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID()))
if(!group || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID()) || !group->isBGGroup())
return;
WorldPacket data;
@@ -587,4 +587,4 @@ void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data )
void WorldSession::HandleChannelDeclineInvite(WorldPacket &recvPacket)
{
sLog.outDebug("Opcode %u", recvPacket.GetOpcode());
}
}
+3 -4
View File
@@ -594,10 +594,6 @@ bool Creature::AIM_Initialize(CreatureAI* ai)
return false;
}
// don't allow AI switch when possessed
if (isPossessed())
return false;
CreatureAI * oldAI = i_AI;
i_motionMaster.Initialize();
i_AI = ai ? ai : FactorySelector::selectAI(this);
@@ -621,6 +617,8 @@ void Creature::DisablePossessedAI()
{
if (!i_AI_possessed) return;
delete i_AI_possessed;
// Signal the old AI that it's been re-enabled
i_AI->OnPossess(false);
}
@@ -1158,6 +1156,7 @@ void Creature::SetLootRecipient(Unit *unit)
if (!unit)
{
m_lootRecipient = 0;
RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_OTHER_TAGGER);
return;
}
+38
View File
@@ -19,7 +19,45 @@
*/
#include "CreatureAI.h"
#include "Creature.h"
#include "Pet.h"
#include "SpellAuras.h"
CreatureAI::~CreatureAI()
{
}
SimpleCharmedAI::SimpleCharmedAI(Unit &u) : me(u)
{
}
void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/)
{
Creature *charmer = (Creature*)me.GetCharmer();
//kill self if charm aura has infinite duration
if(charmer->IsInEvadeMode())
{
Unit::AuraList const& auras = me.GetAurasByType(SPELL_AURA_MOD_CHARM);
for(Unit::AuraList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
if((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->IsPermanent())
{
charmer->Kill(&me);
return;
}
}
if(!charmer->isInCombat())
me.GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
Unit *target = me.getVictim();
if(!target || !charmer->canAttack(target))
{
target = charmer->SelectNearestTarget();
if(!target)
return;
me.GetMotionMaster()->MoveChase(target);
me.Attack(target, true);
}
}
+16 -1
View File
@@ -69,7 +69,22 @@ enum SelectAggroTarget
SELECT_TARGET_FARTHEST,
};
class TRINITY_DLL_SPEC CreatureAI
class TRINITY_DLL_SPEC UnitAI
{
public:
virtual void UpdateAI(const uint32 diff) = 0;
};
class TRINITY_DLL_SPEC SimpleCharmedAI
{
public:
SimpleCharmedAI(Unit &u);
virtual void UpdateAI(const uint32 diff);
private:
Unit &me;
};
class TRINITY_DLL_SPEC CreatureAI : public UnitAI
{
public:
+3 -2
View File
@@ -34,6 +34,9 @@ namespace FactorySelector
{
CreatureAI* selectAI(Creature *creature)
{
//if(creature->isPossessed())
// creature->InitPossessedAI();
// Allow scripting AI for normal creatures and not controlled pets (guardians and mini-pets)
if((!creature->isPet() || !((Pet*)creature)->isControlled()) && !creature->isCharmed())
if(CreatureAI* scriptedAI = Script->GetAI(creature))
@@ -62,8 +65,6 @@ namespace FactorySelector
ai_factory = ai_registry.GetRegistryItem("TotemAI");
else if(creature->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
ai_factory = ai_registry.GetRegistryItem("NullCreatureAI");
else if(creature->isPossessed())
creature->InitPossessedAI();
}
// select by permit check
+1 -1
View File
@@ -63,4 +63,4 @@ extern UNORDERED_MAP<uint32, FormationMember*> CreatureGroupMap;
#define formation_mgr Trinity::Singleton<CreatureGroupManager>::Instance()
#endif
#endif
+2 -6
View File
@@ -6889,7 +6889,7 @@ bool ChatHandler::HandlePossessCommand(const char* args)
if (pUnit->GetTypeId() == TYPEID_PLAYER)
return false;
m_session->GetPlayer()->Possess(pUnit);
pUnit->SetCharmedOrPossessedBy(m_session->GetPlayer(), true);
return true;
}
@@ -6897,11 +6897,7 @@ bool ChatHandler::HandlePossessCommand(const char* args)
bool ChatHandler::HandleUnPossessCommand(const char* args)
{
// Use this command to also unpossess ourselves
if (m_session->GetPlayer()->isPossessed())
m_session->GetPlayer()->UnpossessSelf(false);
else
m_session->GetPlayer()->RemovePossess(false);
m_session->GetPlayer()->RemoveCharmedOrPossessedBy(NULL);
return true;
}
+1 -1
View File
@@ -1403,7 +1403,7 @@ bool Map::CheckGridIntegrity(Creature* c, bool moved) const
Cell xy_cell(xy_val);
if(xy_cell != cur_cell)
{
sLog.outError("ERROR: %s (GUID: %u) X: %f Y: %f (%s) in grid[%u,%u]cell[%u,%u] instead grid[%u,%u]cell[%u,%u]",
sLog.outDebug("ERROR: %s (GUID: %u) X: %f Y: %f (%s) in grid[%u,%u]cell[%u,%u] instead grid[%u,%u]cell[%u,%u]",
(c->GetTypeId()==TYPEID_PLAYER ? "Player" : "Creature"),c->GetGUIDLow(),
c->GetPositionX(),c->GetPositionY(),(moved ? "final" : "original"),
cur_cell.GridX(), cur_cell.GridY(), cur_cell.CellX(), cur_cell.CellY(),
+6
View File
@@ -247,17 +247,23 @@ MapManager::Update(time_t diff)
if( !i_timer.Passed() )
return;
sWorld.RecordTimeDiff(NULL);
ObjectAccessor::Instance().UpdatePlayers(i_timer.GetCurrent());
sWorld.RecordTimeDiff("UpdatePlayers");
for(MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter)
{
checkAndCorrectGridStatesArray(); // debugging code, should be deleted some day
iter->second->Update(i_timer.GetCurrent());
sWorld.RecordTimeDiff("UpdateMap %u", iter->second->GetId());
}
ObjectAccessor::Instance().Update(i_timer.GetCurrent());
sWorld.RecordTimeDiff("UpdateObjectAccessor");
for (TransportSet::iterator iter = m_Transports.begin(); iter != m_Transports.end(); ++iter)
(*iter)->Update(i_timer.GetCurrent());
sWorld.RecordTimeDiff("UpdateTransports");
i_timer.SetCurrent(0);
}
+12
View File
@@ -1648,3 +1648,15 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y,
UpdateGroundPositionZ(x,y,z);
}
void WorldObject::GetClosePointAt(float &x, float &y, float &z, float dist, float angle)
{
angle += GetOrientation();
x += dist * cos(angle);
y += dist * sin(angle);
Trinity::NormalizeMapCoord(x);
Trinity::NormalizeMapCoord(y);
UpdateGroundPositionZ(x, y, z);
}
+6
View File
@@ -394,6 +394,12 @@ class TRINITY_DLL_SPEC WorldObject : public Object
// angle calculated from current orientation
GetNearPoint(NULL,x,y,z,size,distance2d,GetOrientation() + angle);
}
void GetClosePointAt(float &x, float &y, float &z, float dist, float angle);
void GetClosePoint(float &x, float &y, float &z, float dist, float angle)
{
GetPosition(x, y, z);
GetClosePointAt(x, y, z, dist, angle);
}
void GetContactPoint( const WorldObject* obj, float &x, float &y, float &z, float distance2d = CONTACT_DISTANCE) const
{
// angle to face `obj` to `this` using distance includes size of `obj`
+7 -145
View File
@@ -1746,6 +1746,9 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
ResetContestedPvP();
DestroyForNearbyPlayers();
m_clientGUIDs.clear();
// remove player from battleground on far teleport (when changing maps)
if(BattleGround const* bg = GetBattleGround())
{
@@ -19512,150 +19515,12 @@ void Player::HandleFallUnderMap()
}
}
void Player::Possess(Unit *target)
{
if(!target || target == this)
return;
// Don't allow possession of someone else's pet
if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isPet() && target != GetPet())
return;
// Don't allow possession on transports or when in flight; also remove possession from the now-to-be-possessed
if (target->GetTypeId() == TYPEID_PLAYER)
{
if (((Player*)target)->m_transport || ((Player*)target)->isInFlight())
return;
if (target->isPossessing())
((Player*)target)->RemovePossess(true);
}
// Remove any previous possession from the target
if (target->isPossessedByPlayer())
((Player*)target->GetCharmer())->RemovePossess(false);
else if (target->isCharmed())
target->UncharmSelf(); // Target isn't possessed, but charmed; uncharm before possessing
// Remove our previous possession
if (isPossessing())
RemovePossess(true);
else if (GetCharm()) // We are charming a creature, not possessing it; uncharm ourself first
Uncharm();
// Interrupt any current casting of the target
if(target->IsNonMeleeSpellCasted(true))
target->InterruptNonMeleeSpells(true);
// Update the proper unit fields
SetPossessedTarget(target);
// Start channeling packets to possessor
target->AddPlayerToVision(this);
target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction());
target->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
if(target->GetTypeId() == TYPEID_UNIT)
{
((Creature*)target)->InitPossessedAI(); // Initialize the possessed AI
target->StopMoving();
target->GetMotionMaster()->Clear(false);
target->GetMotionMaster()->MoveIdle();
}
target->CombatStop();
target->DeleteThreatList();
// Pets already have a properly initialized CharmInfo, don't overwrite it.
if(target->GetTypeId() == TYPEID_PLAYER || (target->GetTypeId() == TYPEID_UNIT && !((Creature*)target)->isPet()))
{
CharmInfo* charmInfo = target->InitCharmInfo(target);
charmInfo->InitPossessCreateSpells();
}
// Disable control for target player and remove AFK
if(target->GetTypeId() == TYPEID_PLAYER)
{
if(((Player*)target)->isAFK())
((Player*)target)->ToggleAFK();
((Player*)target)->SetViewport(target->GetGUID(), false);
}
// Set current viewport to target unit, controllable
SetViewport(target->GetGUID(), true);
PossessSpellInitialize();
}
void Player::RemovePossess(bool attack)
{
Unit* target = GetCharm();
if(!target || !target->isPossessed())
return;
if(Unit *u = GetCharm())
u->RemoveCharmedOrPossessedBy(this);
// Remove area auras from possessed
Unit::AuraMap& tAuras = target->GetAuras();
for(Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
{
if(itr->second && itr->second->IsAreaAura())
target->RemoveAura(itr);
else
++itr;
}
// Interrupt any current casting of the target
if(target->IsNonMeleeSpellCasted(true))
target->InterruptNonMeleeSpells(true);
RemovePossessedTarget();
// Stop channeling packets back to possessor
target->RemovePlayerFromVision(this);
if(target->GetTypeId() == TYPEID_PLAYER)
((Player*)target)->setFactionForRace(target->getRace());
else if(target->GetTypeId() == TYPEID_UNIT)
{
if(((Creature*)target)->isPet())
{
if(Unit* owner = target->GetOwner())
target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, owner->getFaction());
} else
{
if(CreatureInfo const* cInfo = ((Creature*)target)->GetCreatureInfo())
target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, cInfo->faction_A);
}
}
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
// Remove pet spell action bar
WorldPacket data(SMSG_PET_SPELLS, 8);
data << uint64(0);
m_session->SendPacket(&data);
// Restore original view
SetViewport(GetGUID(), true);
if(target->GetTypeId() == TYPEID_PLAYER)
((Player*)target)->SetViewport(target->GetGUID(), true);
else
{
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
// Reinitialize the pet bar and make the pet come back to the owner
if(((Creature*)target)->isPet())
{
PetSpellInitialize();
if (!target->getVictim())
{
target->GetMotionMaster()->MoveFollow(this, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
}
}
else if (target->isAlive())
/*else if (target->isAlive())
{
// If we're still hostile to our target, continue attacking otherwise reset threat and go home
if (Unit* victim = target->getVictim())
@@ -19682,10 +19547,7 @@ void Player::RemovePossess(bool attack)
// Add high amount of threat on the player
if(attack)
target->AddThreat(this, 1000000.0f);
}
// Disable the assigned possessed AI
((Creature*)target)->DisablePossessedAI();
}
}*/
}
void Player::SetViewport(uint64 guid, bool moveable)
+9 -2
View File
@@ -962,8 +962,14 @@ class TRINITY_DLL_SPEC Player : public Unit
void RemoveFromWorld();
void SetViewport(uint64 guid, bool movable);
void Possess(Unit *target);
void RemovePossess(bool attack = true);
void RemovePossess(bool attack = true);
void StopCharmOrPossess()
{
if(isPossessing())
RemovePossess(true);
else if(GetCharm())
Uncharm();
}
WorldObject* GetFarsightTarget() const;
void ClearFarsight();
void RemoveFarsightTarget();
@@ -2430,6 +2436,7 @@ class TRINITY_DLL_SPEC Player : public Unit
MapReference m_mapRef;
void UpdateCharmedAI();
UnitAI *i_AI;
};
void AddItemsSetItem(Player*player,Item *item);
+1 -1
View File
@@ -26,7 +26,7 @@
#include "ObjectMgr.h"
// Character Dump tables
#define DUMP_TABLE_COUNT 19
#define DUMP_TABLE_COUNT 18
struct DumpTable
{
+15 -5
View File
@@ -896,23 +896,33 @@ enum Targets
TARGET_DEST_TARGET_BACK = 65, // uses in teleport behind spells
TARGET_DEST_TARGET_RIGHT = 66,
TARGET_DEST_TARGET_LEFT = 67,
TARGET_DEST_TARGET_ENEMY_UNKNOWN2 = 70,
TARGET_DEST_TARGET_FRONT_LEFT = 68,
TARGET_DEST_TARGET_BACK_LEFT = 69,
TARGET_DEST_TARGET_BACK_RIGHT = 70,
TARGET_DEST_TARGET_FRONT_RIGHT = 71,
TARGET_DEST_CASTER_RANDOM = 72,
TARGET_DEST_CASTER_RADIUS = 73,
TARGET_DEST_TARGET_RANDOM = 74,
TARGET_DEST_TARGET_RADIUS = 75,
TARGET_DEST_CHANNEL = 76,
TARGET_SINGLE_ENEMY = 77,
TARGET_UNIT_CHANNEL = 77,
TARGET_DEST_CASTER_FRONT_UNKNOWN = 78,
TARGET_DEST_TABLE_UNKNOWN2 = 80,
TARGET_DEST_DEST_FRONT = 78,
TARGET_DEST_DEST_BACK = 79,
TARGET_DEST_DEST_RIGHT = 80,
TARGET_DEST_DEST_LEFT = 81,
TARGET_DEST_DEST_FRONT_LEFT = 82,
TARGET_DEST_DEST_BACK_LEFT = 83,
TARGET_DEST_DEST_BACK_RIGHT = 84,
TARGET_DEST_DEST_FRONT_RIGHT = 85,
TARGET_DEST_DEST_RANDOM = 86,
TARGET_DEST_DEST = 87,
TARGET_UNIT_AREA_ALL_CHANNEL = 88,
TARGET_DEST_TRAJ = 89,
TARGET_UNIT_MINIPET = 90,
TARGET_CORPSE_AREA_ENEMY_PLAYER = 93,
};
#define TOTAL_SPELL_TARGETS 91
#define TOTAL_SPELL_TARGETS 94
enum SpellMissInfo
{
+116 -100
View File
@@ -171,6 +171,7 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster )
return false;
*data >> m_targetMask;
sLog.outDebug("Spell read, target mask = %u", m_targetMask);
if(m_targetMask == TARGET_FLAG_SELF)
return true;
@@ -229,6 +230,7 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster )
void SpellCastTargets::write ( WorldPacket * data )
{
*data << uint32(m_targetMask);
sLog.outDebug("Spell write, target mask = %u", m_targetMask);
if( m_targetMask & ( TARGET_FLAG_UNIT | TARGET_FLAG_PVP_CORPSE | TARGET_FLAG_OBJECT | TARGET_FLAG_OBJECT_UNK | TARGET_FLAG_CORPSE | TARGET_FLAG_UNK2 ) )
{
@@ -276,6 +278,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
ASSERT( info == sSpellStore.LookupEntry( info->Id ) && "`info` must be pointer to sSpellStore element");
m_spellInfo = info;
m_customAttr = spellmgr.GetSpellCustomAttr(m_spellInfo->Id);
m_caster = Caster;
m_selfContainer = NULL;
m_triggeringContainer = triggeringContainer;
@@ -1012,7 +1015,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
{
m_caster->CombatStart(unit);
}
else if(spellmgr.GetSpellCustomAttr(m_spellInfo->Id) & SPELL_ATTR_CU_AURA_CC)
else if(m_customAttr & SPELL_ATTR_CU_AURA_CC)
{
if(!unit->IsStandState())
unit->SetStandState(PLAYER_STATE_NONE);
@@ -1067,7 +1070,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
}
unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_HITBYSPELL);
if(spellmgr.GetSpellCustomAttr(m_spellInfo->Id) & SPELL_ATTR_CU_AURA_CC)
if(m_customAttr & SPELL_ATTR_CU_AURA_CC)
unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CC);
}
else
@@ -1138,12 +1141,11 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
}
//This is not needed with procflag patch
/*if(spellmgr.GetSpellCustomAttr(m_spellInfo->Id) && m_originalCaster)
/*if(m_originalCaster)
{
uint32 flag = spellmgr.GetSpellCustomAttr(m_spellInfo->Id);
if(flag & SPELL_ATTR_CU_EFFECT_HEAL)
if(m_customAttr & SPELL_ATTR_CU_EFFECT_HEAL)
m_originalCaster->ProcDamageAndSpell(unit, PROC_FLAG_HEAL, PROC_FLAG_NONE, 0, GetSpellSchoolMask(m_spellInfo), m_spellInfo);
if(m_originalCaster != unit && (flag & SPELL_ATTR_CU_EFFECT_DAMAGE))
if(m_originalCaster != unit && (m_customAttr & SPELL_ATTR_CU_EFFECT_DAMAGE))
m_originalCaster->ProcDamageAndSpell(unit, PROC_FLAG_HIT_SPELL, PROC_FLAG_STRUCK_SPELL, 0, GetSpellSchoolMask(m_spellInfo), m_spellInfo);
}*/
}
@@ -1582,7 +1584,6 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
AddItemTarget(m_targets.getItemTarget(), i);
}break;
case TARGET_DEST_TABLE_UNKNOWN2:
case TARGET_TABLE_X_Y_Z_COORDINATES:
if(SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id))
{
@@ -1605,9 +1606,9 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
case TARGET_IN_FRONT_OF_CASTER:
case TARGET_UNIT_CONE_ENEMY_UNKNOWN:
if(spellmgr.GetSpellCustomAttr(m_spellInfo->Id) & SPELL_ATTR_CU_CONE_BACK)
if(m_customAttr & SPELL_ATTR_CU_CONE_BACK)
SearchAreaTarget(TagUnitMap, radius, PUSH_IN_BACK, SPELL_TARGETS_AOE_DAMAGE);
else if(spellmgr.GetSpellCustomAttr(m_spellInfo->Id) & SPELL_ATTR_CU_CONE_LINE)
else if(m_customAttr & SPELL_ATTR_CU_CONE_LINE)
SearchAreaTarget(TagUnitMap, radius, PUSH_IN_LINE, SPELL_TARGETS_AOE_DAMAGE);
else
SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_AOE_DAMAGE);
@@ -1831,15 +1832,12 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
float x, y, z, angle, dist;
if (m_spellInfo->EffectRadiusIndex[i])
dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
else
dist = 3.0f;//do we need this?
if (cur == TARGET_DEST_CASTER_RANDOM)
dist *= rand_norm(); // This case we need to consider caster size
else
dist -= m_caster->GetObjectSize(); // Size is calculated in GetNearPoint(), but we do not need it
//need a new function to remove this repeated work
float objSize = m_caster->GetObjectSize();
dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
if(dist < objSize)
dist = objSize;
else if(cur == TARGET_DEST_CASTER_RANDOM)
dist = objSize + (dist - objSize) * rand_norm();
switch(cur)
{
@@ -1849,7 +1847,6 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
case TARGET_DEST_CASTER_FRONT_RIGHT:angle = M_PI/4; break;
case TARGET_MINION:
case TARGET_DEST_CASTER_FRONT_LEAP:
case TARGET_DEST_CASTER_FRONT_UNKNOWN:
case TARGET_DEST_CASTER_FRONT: angle = 0.0f; break;
case TARGET_DEST_CASTER_BACK: angle = M_PI; break;
case TARGET_DEST_CASTER_RIGHT: angle = M_PI/2; break;
@@ -1857,7 +1854,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
default: angle = rand_norm()*2*M_PI; break;
}
m_caster->GetClosePoint(x, y, z, 0, dist, angle);
m_caster->GetClosePoint(x, y, z, dist, angle);
m_targets.setDestination(x, y, z); // do not know if has ground visual
}break;
@@ -1883,15 +1880,12 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
float x, y, z, angle, dist;
if (m_spellInfo->EffectRadiusIndex[i])
dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
else
dist = 3.0f;//do we need this?
if (cur == TARGET_DEST_TARGET_RANDOM)
dist *= rand_norm(); // This case we need to consider caster size
else
dist -= target->GetObjectSize(); // Size is calculated in GetNearPoint(), but we do not need it
//need a new function to remove this repeated work
float objSize = target->GetObjectSize();
dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
if(dist < objSize)
dist = objSize;
else if(cur == TARGET_DEST_CASTER_RANDOM)
dist = objSize + (dist - objSize) * rand_norm();
switch(cur)
{
@@ -1899,10 +1893,14 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
case TARGET_DEST_TARGET_BACK: angle = M_PI; break;
case TARGET_DEST_TARGET_RIGHT: angle = M_PI/2; break;
case TARGET_DEST_TARGET_LEFT: angle = -M_PI/2; break;
case TARGET_DEST_TARGET_FRONT_LEFT: angle = -M_PI/4; break;
case TARGET_DEST_TARGET_BACK_LEFT: angle = -3*M_PI/4; break;
case TARGET_DEST_TARGET_BACK_RIGHT: angle = 3*M_PI/4; break;
case TARGET_DEST_TARGET_FRONT_RIGHT:angle = M_PI/4; break;
default: angle = rand_norm()*2*M_PI; break;
}
target->GetClosePoint(x, y, z, 0, dist, angle);
target->GetClosePoint(x, y, z, dist, angle);
m_targets.setDestination(x, y, z); // do not know if has ground visual
}break;
@@ -1914,61 +1912,59 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
break;
}
if(cur == TARGET_DEST_DEST)
break;
float x, y, z, angle, dist;
dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
if (cur == TARGET_DEST_DEST_RANDOM)
dist *= rand_norm();
switch(cur)
{
case TARGET_DEST_DEST_RANDOM:
{
float x, y, z, dist, px, py, pz;
dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
x = m_targets.m_destX;
y = m_targets.m_destY;
z = m_targets.m_destZ;
m_caster->GetRandomPoint(x, y, z, dist, px, py, pz);
m_targets.setDestination(px, py, pz);
}
break;
case TARGET_DEST_DEST:
break;
case TARGET_DEST_DEST_FRONT: angle = 0.0f; break;
case TARGET_DEST_DEST_BACK: angle = M_PI; break;
case TARGET_DEST_DEST_RIGHT: angle = M_PI/2; break;
case TARGET_DEST_DEST_LEFT: angle = -M_PI/2; break;
case TARGET_DEST_DEST_FRONT_LEFT: angle = -M_PI/4; break;
case TARGET_DEST_DEST_BACK_LEFT: angle = -3*M_PI/4; break;
case TARGET_DEST_DEST_BACK_RIGHT: angle = 3*M_PI/4; break;
case TARGET_DEST_DEST_FRONT_RIGHT:angle = M_PI/4; break;
default: angle = rand_norm()*2*M_PI; break;
}
x = m_targets.m_destX;
y = m_targets.m_destY;
z = m_targets.m_destZ;
m_caster->GetClosePointAt(x, y, z, dist, angle);
m_targets.setDestination(x, y, z); // do not know if has ground visual
}break;
default:
break;
}
if (unMaxTargets && TagUnitMap.size() > unMaxTargets)
if(unMaxTargets)
{
// make sure one unit is always removed per iteration
uint32 removed_utarget = 0;
for (std::list<Unit*>::iterator itr = TagUnitMap.begin(), next; itr != TagUnitMap.end(); itr = next)
if(m_targets.getUnitTarget())
{
next = itr;
++next;
if (!*itr) continue;
if ((*itr) == m_targets.getUnitTarget())
{
TagUnitMap.erase(itr);
removed_utarget = 1;
// break;
}
TagUnitMap.remove(m_targets.getUnitTarget());
if(m_spellInfo->Id != 5246) //Intimidating Shout
--unMaxTargets;
}
// remove random units from the map
while (TagUnitMap.size() > unMaxTargets - removed_utarget)
std::list<Unit*>::iterator itr;
while(TagUnitMap.size() > unMaxTargets)
{
uint32 poz = urand(0, TagUnitMap.size()-1);
for (std::list<Unit*>::iterator itr = TagUnitMap.begin(); itr != TagUnitMap.end(); ++itr, --poz)
{
if (!*itr) continue;
if (!poz)
{
TagUnitMap.erase(itr);
break;
}
}
itr = TagUnitMap.begin();
advance(itr, urand(0, TagUnitMap.size() - 1));
TagUnitMap.erase(itr);
}
// the player's target will always be added to the map
if (removed_utarget && m_targets.getUnitTarget())
if(m_targets.getUnitTarget() && m_spellInfo->Id != 5246)
TagUnitMap.push_back(m_targets.getUnitTarget());
}
}
@@ -2045,7 +2041,8 @@ void Spell::prepare(SpellCastTargets * targets, Aura* triggeredByAura)
// set timer base at cast time
ReSetTimer();
if(m_IsTriggeredSpell)
//item: first cast may destroy item and second cast causes crash
if(m_IsTriggeredSpell || !m_casttime && !m_spellInfo->StartRecoveryTime && !m_castItemGUID && GetCurrentContainer() == CURRENT_GENERIC_SPELL)
cast(true);
else
{
@@ -2161,16 +2158,8 @@ void Spell::cast(bool skipCheck)
FillTargetMap();
if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(m_spellInfo->Id))
{
for(std::vector<int32>::const_iterator i = spell_triggered->begin(); i != spell_triggered->end(); ++i)
{
if(spell_triggered < 0)
m_caster->RemoveAurasDueToSpell(-(*i));
else
m_caster->CastSpell(m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster, *i, true);
}
}
if(m_customAttr & SPELL_ATTR_CU_DIRECT_DAMAGE)
CalculateDamageDoneForAllTargets();
// traded items have trade slot instead of guid in m_itemTargetGUID
// set to real guid to be sent later to the client
@@ -2189,7 +2178,7 @@ void Spell::cast(bool skipCheck)
if(!m_IsTriggeredSpell)
{
TakePower();
//TakePower();
TakeReagents(); // we must remove reagents before HandleEffects to allow place crafted item in same slot
}
@@ -2202,8 +2191,6 @@ void Spell::cast(bool skipCheck)
SendCastResult(castResult);
SendSpellGo(); // we must send smsg_spell_go packet before m_castItem delete in TakeCastItem()...
CalculateDamageDoneForAllTargets();
// Okay, everything is prepared. Now we need to distinguish between immediate and evented delayed spells
if (m_spellInfo->speed > 0.0f && !IsChanneledSpell(m_spellInfo))
{
@@ -2223,20 +2210,20 @@ void Spell::cast(bool skipCheck)
handle_immediate();
}
// Clear combo at finish state
if(m_caster->GetTypeId() == TYPEID_PLAYER && NeedsComboPoints(m_spellInfo))
if(!m_IsTriggeredSpell)
{
// Not drop combopoints if negative spell and if any miss on enemy exist
bool needDrop = true;
//if (!IsPositiveSpell(m_spellInfo->Id))
for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
if (ihit->missCondition != SPELL_MISS_NONE && ihit->missCondition != SPELL_MISS_MISS/* && ihit->targetGUID!=m_caster->GetGUID()*/)
{
needDrop = false;
break;
}
if (needDrop)
((Player*)m_caster)->ClearComboPoints();
TakePower();
}
if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(m_spellInfo->Id))
{
for(std::vector<int32>::const_iterator i = spell_triggered->begin(); i != spell_triggered->end(); ++i)
{
if(spell_triggered < 0)
m_caster->RemoveAurasDueToSpell(-(*i));
else
m_caster->CastSpell(m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster, *i, true);
}
}
SetExecutedCurrently(false);
@@ -3256,9 +3243,25 @@ void Spell::TakeCastItem()
void Spell::TakePower()
{
if(m_CastItem || m_triggeredByAuraSpell)
if(m_CastItem || m_triggeredByAuraSpell || !m_powerCost)
return;
bool hit = true;
if(m_caster->GetTypeId() == TYPEID_PLAYER)
{
if(m_spellInfo->powerType == POWER_RAGE || m_spellInfo->powerType == POWER_ENERGY)
if(uint64 targetGUID = m_targets.getUnitTargetGUID())
for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
if(ihit->targetGUID == targetGUID)
{
if(ihit->missCondition != SPELL_MISS_NONE && ihit->missCondition != SPELL_MISS_MISS/* && ihit->targetGUID!=m_caster->GetGUID()*/)
hit = false;
break;
}
if(hit && NeedsComboPoints(m_spellInfo))
((Player*)m_caster)->ClearComboPoints();
}
// health as power used
if(m_spellInfo->powerType == POWER_HEALTH)
{
@@ -3280,7 +3283,10 @@ void Spell::TakePower()
return;
}
m_caster->ModifyPower(powerType, -(int32)m_powerCost);
if(hit)
m_caster->ModifyPower(powerType, -m_powerCost);
else
m_caster->ModifyPower(powerType, -irand(0, m_powerCost/4));
// Set the five second timer
if (powerType == POWER_MANA && m_powerCost > 0)
@@ -5326,6 +5332,10 @@ bool Spell::CheckTarget( Unit* target, uint32 eff, bool hitPhase )
return false;
}
//Do not check LOS for triggered spells
if(m_IsTriggeredSpell)
return true;
//Check targets for LOS visibility (except spells without range limitations )
switch(m_spellInfo->Effect[eff])
{
@@ -5630,8 +5640,14 @@ int32 Spell::CalculateDamageDone(Unit *unit, const uint32 effectMask, float *mul
break;
}
if(m_damage > 0 && m_originalCaster)
m_damage = m_originalCaster->SpellDamageBonus(unit, m_spellInfo, m_damage, SPELL_DIRECT_DAMAGE);
if(m_damage > 0)
{
if(IsAreaEffectTarget[m_spellInfo->EffectImplicitTargetA[i]] || IsAreaEffectTarget[m_spellInfo->EffectImplicitTargetB[i]])
{
if(int32 reducedPct = unit->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE))
m_damage = m_damage * (100 + reducedPct) / 100;
}
}
if(m_applyMultiplierMask & (1 << i))
{
m_damage *= m_damageMultipliers[i];
+2
View File
@@ -600,6 +600,8 @@ class Spell
// we can't store original aura link to prevent access to deleted auras
// and in same time need aura data and after aura deleting.
SpellEntry const* m_triggeredByAuraSpell;
uint32 m_customAttr;
};
namespace Trinity
+174 -123
View File
@@ -612,10 +612,13 @@ void Aura::Update(uint32 diff)
// update before applying (aura can be removed in TriggerSpell or PeriodicTick calls)
m_periodicTimer += m_modifier.periodictime;
if(m_isTrigger)
TriggerSpell();
else
PeriodicTick();
if(!m_target->hasUnitState(UNIT_STAT_ISOLATED))
{
if(m_isTrigger)
TriggerSpell();
else
PeriodicTick();
}
}
}
}
@@ -633,6 +636,9 @@ void AreaAura::Update(uint32 diff)
switch(m_areaAuraType)
{
case AREA_AURA_PARTY:
caster->GetPartyMember(targets, m_radius);
break;
case AREA_AURA_RAID:
caster->GetRaidMember(targets, m_radius);
break;
@@ -705,39 +711,13 @@ void AreaAura::Update(uint32 diff)
}
else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group
{
// not check group if target == owner or target == pet
if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
{
Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
Group *pGroup = check ? check->GetGroup() : NULL;
if( pGroup )
{
Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
if(!checkTarget || !pGroup->SameSubGroup(check, checkTarget))
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
}
else
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
}
if(!tmp_target->IsInPartyWith(caster))
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
}
else if( m_areaAuraType == AREA_AURA_RAID) // TODO: fix me!
{
// not check group if target == owner or target == pet
if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
{
Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
Group *pGroup = check ? check->GetGroup() : NULL;
if( pGroup )
{
Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
if(!checkTarget)
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
}
else
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
}
if(!tmp_target->IsInRaidWith(caster))
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
}
else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER )
{
@@ -836,15 +816,6 @@ void Aura::_AddAura()
// not call total regen auras at adding
switch (m_modifier.m_auraname)
{
/*case SPELL_AURA_PERIODIC_DAMAGE:
case SPELL_AURA_PERIODIC_LEECH:
if(caster)
m_modifier.m_amount = caster->SpellDamageBonus(m_target, m_spellProto, m_modifier.m_amount, DOT);
break;
case SPELL_AURA_PERIODIC_HEAL:
if(caster)
m_modifier.m_amount = caster->SpellHealingBonus(m_spellProto, m_modifier.m_amount, DOT, m_target);
break;*/
case SPELL_AURA_OBS_MOD_HEALTH:
case SPELL_AURA_OBS_MOD_MANA:
m_periodicTimer = m_modifier.periodictime;
@@ -2976,7 +2947,7 @@ void Aura::HandleAuraModScale(bool apply, bool Real)
m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply);
}
void Aura::HandleModPossess(bool apply, bool Real)
/*void Aura::HandleModPossess(bool apply, bool Real)
{
if(!Real)
return;
@@ -2994,12 +2965,28 @@ void Aura::HandleModPossess(bool apply, bool Real)
if( apply )
{
if (caster->GetTypeId() == TYPEID_PLAYER)
((Player*)caster)->Possess(m_target);
m_target->SetCharmerGUID(GetCasterGUID());
m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
caster->SetCharm(m_target);
m_target->CombatStop();
m_target->DeleteThreatList();
if(m_target->GetTypeId() == TYPEID_UNIT)
{
m_target->StopMoving();
m_target->GetMotionMaster()->Clear();
m_target->GetMotionMaster()->MoveIdle();
CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
charmInfo->InitPossessCreateSpells();
}
if(caster->GetTypeId() == TYPEID_PLAYER)
{
((Player*)caster)->PossessSpellInitialize();
}
}
else
m_target->UnpossessSelf(true);
/*{
{
m_target->SetCharmerGUID(0);
if(m_target->GetTypeId() == TYPEID_PLAYER)
@@ -3028,7 +3015,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
}
}
if(caster->GetTypeId() == TYPEID_PLAYER)
((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);*/
((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
}
void Aura::HandleModPossessPet(bool apply, bool Real)
@@ -3055,14 +3042,12 @@ void Aura::HandleModPossessPet(bool apply, bool Real)
if(apply)
{
((Player*)caster)->Possess(m_target);
pet->StopMoving();
pet->GetMotionMaster()->Clear();
pet->GetMotionMaster()->MoveIdle();
}
else
{
((Player*)caster)->RemovePossess(false);
/*pet->StopMoving();
pet->GetMotionMaster()->Clear();
pet->GetMotionMaster()->MoveIdle();*/
pet->AttackStop();
pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
pet->SetUnitMovementFlags(MOVEMENTFLAG_NONE);
@@ -3079,93 +3064,85 @@ void Aura::HandleModCharm(bool apply, bool Real)
return;
Unit* caster = GetCaster();
if(!caster)
return;
if( apply )
if(int32(m_target->getLevel()) <= m_modifier.m_amount)
{
if(!caster)
return;
if(int32(m_target->getLevel()) > m_modifier.m_amount)
return;
m_target->SetCharmerGUID(GetCasterGUID());
m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
m_target->CastStop(m_target==caster ? GetId() : 0);
caster->SetCharm(m_target);
m_target->CombatStop();
m_target->DeleteThreatList();
if(m_target->GetTypeId() == TYPEID_UNIT)
if( apply )
{
((Creature*)m_target)->AIM_Initialize();
CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
charmInfo->InitCharmCreateSpells();
charmInfo->SetReactState( REACT_DEFENSIVE );
m_target->SetCharmerGUID(GetCasterGUID());
m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
m_target->CastStop(m_target==caster ? GetId() : 0);
caster->SetCharm(m_target);
if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
m_target->CombatStop();
m_target->DeleteThreatList();
if(m_target->GetTypeId() == TYPEID_UNIT)
{
CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
((Creature*)m_target)->AIM_Initialize();
CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
charmInfo->InitCharmCreateSpells();
charmInfo->SetReactState( REACT_DEFENSIVE );
if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
{
//to prevent client crash
m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
//just to enable stat window
charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
//if charmed two demons the same session, the 2nd gets the 1st one's name
m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
{
//to prevent client crash
m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
//just to enable stat window
charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
//if charmed two demons the same session, the 2nd gets the 1st one's name
m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
}
}
}
}
if(caster->GetTypeId() == TYPEID_PLAYER)
{
((Player*)caster)->CharmSpellInitialize();
if(caster->GetTypeId() == TYPEID_PLAYER)
{
((Player*)caster)->CharmSpellInitialize();
}
}
}
else
{
m_target->SetCharmerGUID(0);
if(m_target->GetTypeId() == TYPEID_PLAYER)
((Player*)m_target)->setFactionForRace(m_target->getRace());
else
{
CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
m_target->SetCharmerGUID(0);
// restore faction
if(((Creature*)m_target)->isPet())
if(m_target->GetTypeId() == TYPEID_PLAYER)
((Player*)m_target)->setFactionForRace(m_target->getRace());
else
{
if(Unit* owner = m_target->GetOwner())
m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
else if(cinfo)
CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
// restore faction
if(((Creature*)m_target)->isPet())
{
if(Unit* owner = m_target->GetOwner())
m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
else if(cinfo)
m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
}
else if(cinfo) // normal creature
m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
}
else if(cinfo) // normal creature
m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
// restore UNIT_FIELD_BYTES_0
if(caster && cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
{
CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
if(cainfo && cainfo->bytes0 != 0)
m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
else
m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);
// restore UNIT_FIELD_BYTES_0
if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
{
CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
if(cainfo && cainfo->bytes0 != 0)
m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
else
m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);
if(m_target->GetCharmInfo())
m_target->GetCharmInfo()->SetPetNumber(0, true);
else
sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId());
if(m_target->GetCharmInfo())
m_target->GetCharmInfo()->SetPetNumber(0, true);
else
sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId());
}
}
((Creature*)m_target)->AIM_Initialize();
if(((Creature*)m_target)->AI() && caster)
((Creature*)m_target)->AI()->AttackStart(caster);
}
if(caster)
{
caster->SetCharm(0);
if(caster->GetTypeId() == TYPEID_PLAYER)
@@ -3175,9 +3152,15 @@ void Aura::HandleModCharm(bool apply, bool Real)
data << uint32(0);
((Player*)caster)->GetSession()->SendPacket(&data);
}
if(m_target->GetTypeId() == TYPEID_UNIT)
{
((Creature*)m_target)->AIM_Initialize();
if (((Creature*)m_target)->AI())
((Creature*)m_target)->AI()->AttackStart(caster);
}
}
}
}
}*/
void Aura::HandleModConfuse(bool apply, bool Real)
{
@@ -6655,3 +6638,71 @@ void Aura::HandleModAttackerSpellHitChance(bool apply, bool Real)
//cloak of shadows : flare
m_target->ApplySpellImmune(31224, IMMUNITY_ID, 1543, apply);
}
void Aura::HandleModPossess(bool apply, bool Real)
{
if(!Real)
return;
Unit* caster = GetCaster();
if(caster && caster->GetTypeId() == TYPEID_UNIT)
{
HandleModCharm(apply, Real);
return;
}
if(apply)
{
if(m_target->getLevel() > m_modifier.m_amount)
return;
m_target->SetCharmedOrPossessedBy(caster, true);
}
else
m_target->RemoveCharmedOrPossessedBy(caster);
}
void Aura::HandleModPossessPet(bool apply, bool Real)
{
if(!Real)
return;
Unit* caster = GetCaster();
if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
if(caster->GetPet() != m_target)
return;
if(apply)
m_target->SetCharmedOrPossessedBy(caster, true);
else
{
m_target->RemoveCharmedOrPossessedBy(caster);
// Reinitialize the pet bar and make the pet come back to the owner
((Player*)caster)->PetSpellInitialize();
if(!m_target->getVictim())
{
m_target->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
m_target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
}
}
}
void Aura::HandleModCharm(bool apply, bool Real)
{
if(!Real)
return;
Unit* caster = GetCaster();
if(apply)
{
if(int32(m_target->getLevel()) > m_modifier.m_amount)
return;
m_target->SetCharmedOrPossessedBy(caster, false);
}
else
m_target->RemoveCharmedOrPossessedBy(caster);
}
+11 -6
View File
@@ -325,7 +325,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
}
// Meteor like spells (divided damage to targets)
if(spellmgr.GetSpellCustomAttr(m_spellInfo->Id) & SPELL_ATTR_CU_SHARE_DAMAGE)
if(m_customAttr & SPELL_ATTR_CU_SHARE_DAMAGE)
{
uint32 count = 0;
for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
@@ -682,8 +682,11 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
}
}
if(damage >= 0)
m_damage+= damage;
if(m_originalCaster)
damage = m_originalCaster->SpellDamageBonus(unitTarget, m_spellInfo, damage, SPELL_DIRECT_DAMAGE);
if(damage > 0)
m_damage += damage;
}
}
@@ -2367,7 +2370,9 @@ void Spell::EffectPowerBurn(uint32 i)
new_damage = int32(new_damage*multiplier);
//m_damage+=new_damage; should not apply spell bonus
//TODO: no log
unitTarget->ModifyHealth(-new_damage);
//unitTarget->ModifyHealth(-new_damage);
if(m_originalCaster)
m_originalCaster->DealDamage(unitTarget, new_damage);
}
void Spell::EffectHeal( uint32 /*i*/ )
@@ -3759,7 +3764,7 @@ void Spell::EffectSummonPossessed(uint32 i)
TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
Creature* c = m_caster->SummonCreature(creatureEntry, px, py, pz, m_caster->GetOrientation(), summonType, duration);
((Player*)m_caster)->Possess(c);
if(c) c->SetCharmedOrPossessedBy(m_caster, true);
}
void Spell::EffectTeleUnitsFaceCaster(uint32 i)
@@ -6570,4 +6575,4 @@ void Spell::EffectRedirectThreat(uint32 /*i*/)
{
if(unitTarget)
m_caster->SetReducedThreatPercent((uint32)damage, unitTarget->GetGUID());
}
}
+25 -4
View File
@@ -126,11 +126,14 @@ SpellMgr::SpellMgr()
SpellTargetType[i] = TARGET_TYPE_AREA_DEST;
break;
case TARGET_DEST_TARGET_ENEMY:
case TARGET_DEST_TARGET_ENEMY_UNKNOWN:
case TARGET_DEST_TARGET_FRONT:
case TARGET_DEST_TARGET_BACK:
case TARGET_DEST_TARGET_RIGHT:
case TARGET_DEST_TARGET_LEFT:
case TARGET_DEST_TARGET_FRONT_LEFT:
case TARGET_DEST_TARGET_BACK_LEFT:
case TARGET_DEST_TARGET_BACK_RIGHT:
case TARGET_DEST_TARGET_FRONT_RIGHT:
case TARGET_DEST_TARGET_RANDOM:
case TARGET_DEST_TARGET_RADIUS:
SpellTargetType[i] = TARGET_TYPE_DEST_TARGET;
@@ -144,7 +147,6 @@ SpellMgr::SpellMgr()
case TARGET_DEST_CASTER_FRONT:
case TARGET_MINION:
case TARGET_DEST_CASTER_FRONT_LEAP:
case TARGET_DEST_CASTER_FRONT_UNKNOWN:
case TARGET_DEST_CASTER_BACK:
case TARGET_DEST_CASTER_RIGHT:
case TARGET_DEST_CASTER_LEFT:
@@ -152,8 +154,16 @@ SpellMgr::SpellMgr()
case TARGET_DEST_CASTER_RADIUS:
SpellTargetType[i] = TARGET_TYPE_DEST_CASTER;
break;
case TARGET_DEST_DEST_RANDOM:
case TARGET_DEST_DEST:
case TARGET_DEST_DEST_FRONT_LEFT:
case TARGET_DEST_DEST_BACK_LEFT:
case TARGET_DEST_DEST_BACK_RIGHT:
case TARGET_DEST_DEST_FRONT_RIGHT:
case TARGET_DEST_DEST_FRONT:
case TARGET_DEST_DEST_BACK:
case TARGET_DEST_DEST_RIGHT:
case TARGET_DEST_DEST_LEFT:
case TARGET_DEST_DEST_RANDOM:
SpellTargetType[i] = TARGET_TYPE_DEST_DEST;
break;
default:
@@ -475,7 +485,7 @@ bool IsPositiveTarget(uint32 targetA, uint32 targetB)
case TARGET_IN_FRONT_OF_CASTER:
case TARGET_ALL_ENEMY_IN_AREA_CHANNELED:
case TARGET_CURRENT_ENEMY_COORDINATES:
case TARGET_SINGLE_ENEMY:
case TARGET_UNIT_CHANNEL:
return false;
case TARGET_ALL_AROUND_CASTER:
return (targetB == TARGET_ALL_PARTY || targetB == TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER);
@@ -2064,6 +2074,17 @@ void SpellMgr::LoadSpellCustomAttr()
default:
break;
}
switch(spellInfo->Effect[j])
{
case SPELL_EFFECT_SCHOOL_DAMAGE:
case SPELL_EFFECT_WEAPON_DAMAGE:
case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
case SPELL_EFFECT_HEAL:
mSpellCustomAttr[i] |= SPELL_ATTR_CU_DIRECT_DAMAGE;
}
}
if(spellInfo->SpellVisual[0] == 3879)
+7 -1
View File
@@ -416,12 +416,17 @@ inline bool IsAreaAuraEffect(uint32 effect)
inline bool IsDispelSpell(SpellEntry const *spellInfo)
{
//spellsteal is also dispel
if (spellInfo->Effect[0] == SPELL_EFFECT_DISPEL ||
spellInfo->Effect[0] == SPELL_EFFECT_STEAL_BENEFICIAL_BUFF ||
spellInfo->Effect[1] == SPELL_EFFECT_DISPEL ||
spellInfo->Effect[2] == SPELL_EFFECT_DISPEL )
spellInfo->Effect[1] == SPELL_EFFECT_STEAL_BENEFICIAL_BUFF ||
spellInfo->Effect[2] == SPELL_EFFECT_DISPEL ||
spellInfo->Effect[2] == SPELL_EFFECT_STEAL_BENEFICIAL_BUFF)
return true;
return false;
}
inline bool isSpellBreakStealth(SpellEntry const* spellInfo)
{
return !(spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_BREAK_STEALTH);
@@ -745,6 +750,7 @@ inline bool IsProfessionSkill(uint32 skill)
#define SPELL_ATTR_CU_AURA_DOT 0x00000020
#define SPELL_ATTR_CU_AURA_CC 0x00000040
#define SPELL_ATTR_CU_AURA_SPELL 0x00000080
#define SPELL_ATTR_CU_DIRECT_DAMAGE 0x00000100
typedef std::vector<uint32> SpellCustomAttribute;
+23 -18
View File
@@ -982,23 +982,6 @@ void Pet::UpdateAttackPowerAndDamage(bool ranged)
frost = 0;
SetBonusDamage( int32(frost * 0.4f));
}
//force of nature
else if(GetEntry() == 1964)
{
int32 spellDmg = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_NATURE)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_NATURE);
if(spellDmg > 0)
SetBonusDamage(int32(spellDmg * 0.09f));
}
//greater fire elemental
else if(GetEntry() == 15438)
{
if(Unit* shaman = owner->GetOwner())
{
int32 spellDmg = int32(shaman->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - shaman->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
if(spellDmg > 0)
SetBonusDamage(int32(spellDmg * 0.4f));
}
}
}
SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val + bonusAP);
@@ -1024,11 +1007,33 @@ void Pet::UpdateDamagePhysical(WeaponAttackType attType)
if(attType > BASE_ATTACK)
return;
float bonusDamage = 0.0f;
if(Unit* owner = GetOwner())
{
//force of nature
if(GetEntry() == 1964)
{
int32 spellDmg = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_NATURE)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_NATURE);
if(spellDmg > 0)
bonusDamage = spellDmg * 0.09f;
}
//greater fire elemental
else if(GetEntry() == 15438)
{
if(Unit* shaman = owner->GetOwner())
{
int32 spellDmg = int32(shaman->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - shaman->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
if(spellDmg > 0)
bonusDamage = spellDmg * 0.4f;
}
}
}
UnitMods unitMod = UNIT_MOD_DAMAGE_MAINHAND;
float att_speed = float(GetAttackTime(BASE_ATTACK))/1000.0f;
float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed;
float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed + bonusDamage;
float base_pct = GetModifierValue(unitMod, BASE_PCT);
float total_value = GetModifierValue(unitMod, TOTAL_VALUE);
float total_pct = GetModifierValue(unitMod, TOTAL_PCT);
+2 -2
View File
@@ -172,9 +172,9 @@ void TemporarySummon::Summon(TempSummonType type, uint32 lifetime)
void TemporarySummon::UnSummon()
{
CombatStop();
RemoveCharmedOrPossessedBy(NULL);
UnpossessSelf(false);
CombatStop();
CleanupsBeforeDelete();
AddObjectToRemoveList();
+260 -72
View File
@@ -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;
}
+28 -39
View File
@@ -364,27 +364,28 @@ enum DeathState
enum UnitState
{
UNIT_STAT_DIED = 0x0001,
UNIT_STAT_MELEE_ATTACKING = 0x0002, // player is melee attacking someone
//UNIT_STAT_MELEE_ATTACK_BY = 0x0004, // player is melee attack by someone
UNIT_STAT_STUNNED = 0x0008,
UNIT_STAT_ROAMING = 0x0010,
UNIT_STAT_CHASE = 0x0020,
UNIT_STAT_SEARCHING = 0x0040,
UNIT_STAT_FLEEING = 0x0080,
UNIT_STAT_DIED = 0x00000001,
UNIT_STAT_MELEE_ATTACKING = 0x00000002, // player is melee attacking someone
//UNIT_STAT_MELEE_ATTACK_BY = 0x00000004, // player is melee attack by someone
UNIT_STAT_STUNNED = 0x00000008,
UNIT_STAT_ROAMING = 0x00000010,
UNIT_STAT_CHASE = 0x00000020,
UNIT_STAT_SEARCHING = 0x00000040,
UNIT_STAT_FLEEING = 0x00000080,
UNIT_STAT_IN_FLIGHT = 0x00000100, // player is in flight mode
UNIT_STAT_FOLLOW = 0x00000200,
UNIT_STAT_ROOT = 0x00000400,
UNIT_STAT_CONFUSED = 0x00000800,
UNIT_STAT_DISTRACTED = 0x00001000,
UNIT_STAT_ISOLATED = 0x00002000, // area auras do not affect other players
UNIT_STAT_ATTACK_PLAYER = 0x00004000,
UNIT_STAT_CASTING = 0x00008000,
UNIT_STAT_POSSESSED = 0x00010000,
UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING),
UNIT_STAT_IN_FLIGHT = 0x0100, // player is in flight mode
UNIT_STAT_FOLLOW = 0x0200,
UNIT_STAT_ROOT = 0x0400,
UNIT_STAT_CONFUSED = 0x0800,
UNIT_STAT_DISTRACTED = 0x1000,
UNIT_STAT_ISOLATED = 0x2000, // area auras do not affect other players
UNIT_STAT_ATTACK_PLAYER = 0x4000,
UNIT_STAT_CASTING = 0x8000,
UNIT_STAT_LOST_CONTROL = (UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING),
UNIT_STAT_SIGHTLESS = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_CHASE | UNIT_STAT_SEARCHING),
UNIT_STAT_CANNOT_AUTOATTACK = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_CASTING),
UNIT_STAT_ALL_STATE = 0xffff //(UNIT_STAT_STOPPED | UNIT_STAT_MOVING | UNIT_STAT_IN_COMBAT | UNIT_STAT_IN_FLIGHT)
UNIT_STAT_ALL_STATE = 0xffffffff //(UNIT_STAT_STOPPED | UNIT_STAT_MOVING | UNIT_STAT_IN_COMBAT | UNIT_STAT_IN_FLIGHT)
};
enum UnitMoveType
@@ -937,7 +938,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }
void RemoveSpellbyDamageTaken(uint32 damage, uint32 spell);
uint32 DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss);
uint32 DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage = NULL, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *spellProto = NULL, bool durabilityLoss = true);
void Kill(Unit *pVictim, bool durabilityLoss = true);
void ProcDamageAndSpell(Unit *pVictim, uint32 procAttacker, uint32 procVictim, uint32 procEx, uint32 amount, WeaponAttackType attType = BASE_ATTACK, SpellEntry const *procSpell = NULL);
@@ -1093,35 +1094,24 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
Unit* GetCharmer() const;
Unit* GetCharm() const;
Unit* GetCharmerOrOwner() const { return GetCharmerGUID() ? GetCharmer() : GetOwner(); }
Unit* GetCharmerOrOwnerOrSelf()
Unit* GetCharmerOrOwnerOrSelf() const
{
if(Unit* u = GetCharmerOrOwner())
if(Unit *u = GetCharmerOrOwner())
return u;
return this;
return (Unit*)this;
}
Player* GetCharmerOrOwnerPlayerOrPlayerItself() const;
void SetPet(Pet* pet);
void SetCharm(Unit* pet);
void SetPossessedTarget(Unit* target)
{
if (!target) return;
SetCharm(target);
target->SetCharmerGUID(GetGUID());
target->m_isPossessed = true;
}
void RemovePossessedTarget()
{
if (!GetCharm()) return;
GetCharm()->SetCharmerGUID(0);
GetCharm()->m_isPossessed = false;
SetCharm(0);
}
void SetCharmedOrPossessedBy(Unit* charmer, bool possess);
void RemoveCharmedOrPossessedBy(Unit* charmer);
void RestoreFaction();
bool isCharmed() const { return GetCharmerGUID() != 0; }
bool isPossessed() const { return m_isPossessed; }
bool isPossessedByPlayer() const { return m_isPossessed && IS_PLAYER_GUID(GetCharmerGUID()); }
bool isPossessed() const { return hasUnitState(UNIT_STAT_POSSESSED); }
bool isPossessedByPlayer() const { return hasUnitState(UNIT_STAT_POSSESSED) && IS_PLAYER_GUID(GetCharmerGUID()); }
bool isPossessing() const
{
if(Unit *u = GetCharm())
@@ -1139,7 +1129,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void RemovePlayerFromVision(Player* plr);
void RemoveAllFromVision();
void UncharmSelf();
void UnpossessSelf(bool attack);
Pet* CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id = 0);
@@ -1260,6 +1249,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
// Visibility system
UnitVisibility GetVisibility() const { return m_Visibility; }
void SetVisibility(UnitVisibility x);
void DestroyForNearbyPlayers();
// common function for visibility checks for player/creatures with detection code
virtual bool canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList = false, bool is3dDistance = true) const;
@@ -1510,7 +1500,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
float m_speed_rate[MAX_MOVE_TYPE];
CharmInfo *m_charmInfo;
bool m_isPossessed;
SharedVisionList m_sharedVision;
virtual SpellSchoolMask GetMeleeDamageSchoolMask() const;
+27 -10
View File
@@ -1036,6 +1036,7 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_NO_RESET_TALENT_COST] = sConfig.GetBoolDefault("NoResetTalentsCost", false);
m_configs[CONFIG_SHOW_KICK_IN_WORLD] = sConfig.GetBoolDefault("ShowKickInWorld", false);
m_configs[CONFIG_INTERVAL_LOG_UPDATE] = sConfig.GetIntDefault("RecordUpdateTimeDiffInterval", 60000);
m_configs[CONFIG_MIN_LOG_UPDATE] = sConfig.GetIntDefault("MinRecordUpdateTimeDiff", 10);
std::string forbiddenmaps = sConfig.GetStringDefault("ForbiddenMaps", "");
char * forbiddenMaps = new char[forbiddenmaps.length() + 1];
@@ -1471,14 +1472,29 @@ void World::DetectDBCLang()
sLog.outString("Using %s DBC Locale as default. All available DBC locales: %s",localeNames[m_defaultDbcLocale],availableLocalsStr.empty() ? "<none>" : availableLocalsStr.c_str());
}
void World::RecordTimeDiff(const char *text)
void World::RecordTimeDiff(const char *text, ...)
{
if(m_updateTimeCount != 1)
return;
sLog.outDebugInLine("Difftime ");
sLog.outDebugInLine(text);
uint32 thisTime = getMSTime();
sLog.outDebug(": %u.", getMSTimeDiff(m_currentTime, thisTime));
if(!text)
{
m_currentTime = getMSTime();
return;
}
uint32 thisTime = getMSTime();
uint32 diff = getMSTimeDiff(m_currentTime, thisTime);
if(diff > m_configs[CONFIG_MIN_LOG_UPDATE])
{
va_list ap;
char str [256];
va_start(ap, text);
vsnprintf(str,256,text, ap );
va_end(ap);
sLog.outDetail("Difftime %s: %u.", str, diff);
}
m_currentTime = thisTime;
}
@@ -1493,7 +1509,6 @@ void World::Update(time_t diff)
sLog.outString("Update time diff: %u. Players online: %u.", m_updateTimeSum / m_updateTimeCount, GetActiveSessionCount());
m_updateTimeSum = m_updateTime;
m_updateTimeCount = 1;
m_currentTime = getMSTime();
}
else
{
@@ -1580,8 +1595,8 @@ void World::Update(time_t diff)
}
}
}
RecordTimeDiff("UpdateAuction");
RecordTimeDiff(NULL);
/// <li> Handle session updates when the timer has passed
if (m_timers[WUPDATE_SESSIONS].Passed())
{
@@ -1621,7 +1636,6 @@ void World::Update(time_t diff)
m_timers[WUPDATE_UPTIME].Reset();
WorldDatabase.PExecute("UPDATE uptime SET uptime = %d, maxplayers = %d WHERE starttime = " I64FMTD, tmpDiff, maxClientsNum, uint64(m_startTime));
}
RecordTimeDiff("UpdateWeatherAndUptime");
/// <li> Handle all other objects
if (m_timers[WUPDATE_OBJECTS].Passed())
@@ -1630,16 +1644,20 @@ void World::Update(time_t diff)
///- Update objects when the timer has passed (maps, transport, creatures,...)
MapManager::Instance().Update(diff); // As interval = 0
RecordTimeDiff(NULL);
///- Process necessary scripts
if (!m_scriptSchedule.empty())
ScriptsProcess();
RecordTimeDiff("UpdateScriptsProcess");
sBattleGroundMgr.Update(diff);
RecordTimeDiff("UpdateBattleGroundMgr");
sOutdoorPvPMgr.Update(diff);
RecordTimeDiff("UpdateOutdoorPvPMgr");
}
RecordTimeDiff("UpdateMaps");
RecordTimeDiff(NULL);
// execute callbacks from sql queries that were queued recently
UpdateResultQueue();
RecordTimeDiff("UpdateResultQueue");
@@ -1670,7 +1688,6 @@ void World::Update(time_t diff)
// And last, but not least handle the issued cli commands
ProcessCliCommands();
RecordTimeDiff("UpdateRemainingThings");
}
void World::ForceGameEventUpdate()
+2 -1
View File
@@ -207,6 +207,7 @@ enum WorldConfigs
CONFIG_NO_RESET_TALENT_COST,
CONFIG_SHOW_KICK_IN_WORLD,
CONFIG_INTERVAL_LOG_UPDATE,
CONFIG_MIN_LOG_UPDATE,
CONFIG_ENABLE_SINFO_LOGIN,
CONFIG_VALUE_COUNT
@@ -528,6 +529,7 @@ class World
void SetScriptsVersion(char const* version) { m_ScriptsVersion = version ? version : "unknown scripting library"; }
char const* GetScriptsVersion() { return m_ScriptsVersion.c_str(); }
void RecordTimeDiff(const char * text, ...);
protected:
void _UpdateGameTime();
void ScriptsProcess();
@@ -550,7 +552,6 @@ class World
uint32 m_updateTime, m_updateTimeSum;
uint32 m_updateTimeCount;
uint32 m_currentTime;
void RecordTimeDiff(const char * text);
typedef UNORDERED_MAP<uint32, Weather*> WeatherMap;
WeatherMap m_weathers;
+8 -7
View File
@@ -249,6 +249,14 @@ void WorldSession::LogoutPlayer(bool Save)
if (_player)
{
// Unpossess the current possessed unit of player
_player->StopCharmOrPossess();
// Remove any possession of this player on logout
_player->RemoveCharmedOrPossessedBy(NULL);
_player->DestroyForNearbyPlayers();
if (uint64 lguid = GetPlayer()->GetLootGUID())
DoLootRelease(lguid);
@@ -374,13 +382,6 @@ void WorldSession::LogoutPlayer(bool Save)
if(_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket)
_player->RemoveFromGroup();
// Unpossess the current possessed unit of player
if (_player->isPossessing())
_player->RemovePossess(false);
// Remove any possession of this player on logout
_player->UnpossessSelf(false);
///- Remove the player from the world
// the player may not be in the world when logging out
// e.g if he got disconnected during a transfer to another map