Merge commit 'origin/master' into 330

This commit is contained in:
tomrus88 2009-10-21 23:49:51 +04:00
commit 5e15a6553c
36 changed files with 351 additions and 213 deletions

View file

@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) default NULL, `version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL,
`cache_id` int(10) default '0', `cache_id` int(10) default '0',
`required_8676_01_mangos_creature_template` bit(1) default NULL `required_8693_01_mangos_spell_proc_event` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
-- --
@ -18324,6 +18324,7 @@ INSERT INTO `spell_proc_event` VALUES
(63108, 0x00000000, 5, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (63108, 0x00000000, 5, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(63156, 0x00000000, 0, 0x00000001, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (63156, 0x00000000, 0, 0x00000001, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(63245, 0x00000000, 5, 0x00000100, 0x00800000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (63245, 0x00000000, 5, 0x00000100, 0x00800000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(63320, 0x00000000, 5, 0x00040000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(63730, 0x00000000, 6, 0x00000800, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (63730, 0x00000000, 6, 0x00000800, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(64928, 0x00000000, 11, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0); (64928, 0x00000000, 11, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0);
/*!40000 ALTER TABLE `spell_proc_event` ENABLE KEYS */; /*!40000 ALTER TABLE `spell_proc_event` ENABLE KEYS */;

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_8676_01_mangos_creature_template required_8688_01_mangos_creature_template bit;
-- reverts last update - we now have something better
UPDATE creature_template SET flags_extra = flags_extra & ~(0x200) WHERE npcflag
& (16384|32768);

View file

@ -0,0 +1,4 @@
ALTER TABLE db_version CHANGE COLUMN required_8688_01_mangos_creature_template required_8693_01_mangos_spell_proc_event bit;
DELETE FROM spell_proc_event WHERE entry = 63320;
INSERT INTO spell_proc_event VALUES (63320, 0x00000000, 5, 0x00040000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0);

View file

@ -136,6 +136,8 @@ pkgdata_DATA = \
8608_02_mangos_battleground_events.sql \ 8608_02_mangos_battleground_events.sql \
8618_01_mangos_spell_proc_event.sql \ 8618_01_mangos_spell_proc_event.sql \
8676_01_mangos_creature_template.sql \ 8676_01_mangos_creature_template.sql \
8688_01_mangos_creature_template.sql \
8693_01_mangos_spell_proc_event.sql \
README README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -252,4 +254,6 @@ EXTRA_DIST = \
8608_02_mangos_battleground_events.sql \ 8608_02_mangos_battleground_events.sql \
8618_01_mangos_spell_proc_event.sql \ 8618_01_mangos_spell_proc_event.sql \
8676_01_mangos_creature_template.sql \ 8676_01_mangos_creature_template.sql \
8688_01_mangos_creature_template.sql \
8693_01_mangos_spell_proc_event.sql \
README README

View file

@ -19,6 +19,7 @@
#include "AggressorAI.h" #include "AggressorAI.h"
#include "Errors.h" #include "Errors.h"
#include "Creature.h" #include "Creature.h"
#include "SharedDefines.h"
#include "ObjectAccessor.h" #include "ObjectAccessor.h"
#include "VMapFactory.h" #include "VMapFactory.h"
#include "World.h" #include "World.h"
@ -46,9 +47,9 @@ AggressorAI::MoveInLineOfSight(Unit *u)
if( !m_creature->canFly() && m_creature->GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE ) if( !m_creature->canFly() && m_creature->GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE )
return; return;
if( !(m_creature->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_GHOST) && !m_creature->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_DIED) && u->isTargetableForAttack() && if (!m_creature->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_DIED) && u->isTargetableForAttack() &&
( m_creature->IsHostileTo( u ) /*|| u->getVictim() && m_creature->IsFriendlyTo( u->getVictim() )*/ ) && ( m_creature->IsHostileTo( u ) /*|| u->getVictim() && m_creature->IsFriendlyTo( u->getVictim() )*/ ) &&
u->isInAccessablePlaceFor(m_creature) ) u->isInAccessablePlaceFor(m_creature))
{ {
float attackRadius = m_creature->GetAttackDistance(u); float attackRadius = m_creature->GetAttackDistance(u);
if(m_creature->IsWithinDistInMap(u, attackRadius) && m_creature->IsWithinLOSInMap(u) ) if(m_creature->IsWithinDistInMap(u, attackRadius) && m_creature->IsWithinLOSInMap(u) )

View file

@ -336,7 +336,7 @@ void BattleGroundAV::EndBattleGround(uint32 winner)
// now we have the values give the honor/reputation to the teams: // now we have the values give the honor/reputation to the teams:
uint32 team[BG_TEAMS_COUNT] = { ALLIANCE, HORDE }; uint32 team[BG_TEAMS_COUNT] = { ALLIANCE, HORDE };
uint32 faction[BG_TEAMS_COUNT] = { BG_AV_FACTION_A, BG_AV_FACTION_H }; uint32 faction[BG_TEAMS_COUNT] = { BG_AV_FACTION_A, BG_AV_FACTION_H };
for(uint32 i = 0; i < BG_TEAMS_COUNT; i++) for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
{ {
if (tower_survived[i]) if (tower_survived[i])
{ {
@ -800,6 +800,7 @@ void BattleGroundAV::Reset()
m_RepOwnedGrave = (isBGWeekend) ? BG_AV_REP_OWNED_GRAVE_HOLIDAY : BG_AV_REP_OWNED_GRAVE; m_RepOwnedGrave = (isBGWeekend) ? BG_AV_REP_OWNED_GRAVE_HOLIDAY : BG_AV_REP_OWNED_GRAVE;
m_RepSurviveCaptain = (isBGWeekend) ? BG_AV_REP_SURVIVING_CAPTAIN_HOLIDAY : BG_AV_REP_SURVIVING_CAPTAIN; m_RepSurviveCaptain = (isBGWeekend) ? BG_AV_REP_SURVIVING_CAPTAIN_HOLIDAY : BG_AV_REP_SURVIVING_CAPTAIN;
m_RepSurviveTower = (isBGWeekend) ? BG_AV_REP_SURVIVING_TOWER_HOLIDAY : BG_AV_REP_SURVIVING_TOWER; m_RepSurviveTower = (isBGWeekend) ? BG_AV_REP_SURVIVING_TOWER_HOLIDAY : BG_AV_REP_SURVIVING_TOWER;
m_RepOwnedMine = (isBGWeekend) ? BG_AV_REP_OWNED_MINE_HOLIDAY : BG_AV_REP_OWNED_MINE;
for(uint8 i = 0; i < BG_TEAMS_COUNT; i++) for(uint8 i = 0; i < BG_TEAMS_COUNT; i++)
{ {

View file

@ -1746,11 +1746,12 @@ bool Creature::IsVisibleInGridForPlayer(Player* pl) const
if(pl->isGameMaster()) if(pl->isGameMaster())
return true; return true;
if (GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_INVISIBLE)
return false;
// Live player (or with not release body see live creatures or death creatures with corpse disappearing time > 0 // Live player (or with not release body see live creatures or death creatures with corpse disappearing time > 0
if(pl->isAlive() || pl->GetDeathTimer() > 0) if(pl->isAlive() || pl->GetDeathTimer() > 0)
{ {
if(GetCreatureInfo()->flags_extra & (CREATURE_FLAG_EXTRA_INVISIBLE | CREATURE_FLAG_EXTRA_GHOST))
return false;
return (isAlive() || m_deathTimer > 0 || (m_isDeadByDefault && m_deathState == CORPSE)); return (isAlive() || m_deathTimer > 0 || (m_isDeadByDefault && m_deathState == CORPSE));
} }
@ -1766,8 +1767,8 @@ bool Creature::IsVisibleInGridForPlayer(Player* pl) const
} }
} }
// Dead player see ghosts // Dead player can see ghosts
if (GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_GHOST) if (GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_GHOST_VISIBLE)
return true; return true;
// and not see any other // and not see any other

View file

@ -143,7 +143,6 @@ enum CreatureFlagsExtra
CREATURE_FLAG_EXTRA_NO_XP_AT_KILL = 0x00000040, // creature kill not provide XP CREATURE_FLAG_EXTRA_NO_XP_AT_KILL = 0x00000040, // creature kill not provide XP
CREATURE_FLAG_EXTRA_INVISIBLE = 0x00000080, // creature is always invisible for player (mostly trigger creatures) CREATURE_FLAG_EXTRA_INVISIBLE = 0x00000080, // creature is always invisible for player (mostly trigger creatures)
CREATURE_FLAG_EXTRA_NOT_TAUNTABLE = 0x00000100, // creature is immune to taunt auras and effect attack me CREATURE_FLAG_EXTRA_NOT_TAUNTABLE = 0x00000100, // creature is immune to taunt auras and effect attack me
CREATURE_FLAG_EXTRA_GHOST = 0x00000200, // creature is only visible for dead players
}; };
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform // GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform

View file

@ -247,6 +247,25 @@ enum Difficulty
#define MAX_RAID_DIFFICULTY 4 #define MAX_RAID_DIFFICULTY 4
#define MAX_DIFFICULTY 4 #define MAX_DIFFICULTY 4
enum SpawnMask
{
SPAWNMASK_CONTINENT = 1, // any any maps without spawn modes
SPAWNMASK_DUNGEON_NORMAL = (1 << DUNGEON_DIFFICULTY_NORMAL),
SPAWNMASK_DUNGEON_HEROIC = (1 << DUNGEON_DIFFICULTY_HEROIC),
SPAWNMASK_DUNGEON_ALL = (SPAWNMASK_DUNGEON_NORMAL | SPAWNMASK_DUNGEON_HEROIC),
SPAWNMASK_RAID_10MAN_NORMAL = (1 << RAID_DIFFICULTY_10MAN_NORMAL),
SPAWNMASK_RAID_25MAN_NORMAL = (1 << RAID_DIFFICULTY_25MAN_NORMAL),
SPAWNMASK_RAID_NORMAL_ALL = (SPAWNMASK_RAID_10MAN_NORMAL | SPAWNMASK_RAID_25MAN_NORMAL),
SPAWNMASK_RAID_10MAN_HEROIC = (1 << RAID_DIFFICULTY_10MAN_HEROIC),
SPAWNMASK_RAID_25MAN_HEROIC = (1 << RAID_DIFFICULTY_25MAN_HEROIC),
SPAWNMASK_RAID_HEROIC_ALL = (SPAWNMASK_RAID_10MAN_HEROIC | SPAWNMASK_RAID_25MAN_HEROIC),
SPAWNMASK_RAID_ALL = (SPAWNMASK_RAID_NORMAL_ALL | SPAWNMASK_RAID_HEROIC_ALL),
};
enum FactionTemplateFlags enum FactionTemplateFlags
{ {
FACTION_TEMPLATE_FLAG_CONTESTED_GUARD = 0x00001000, // faction will attack players that were involved in PvP combats FACTION_TEMPLATE_FLAG_CONTESTED_GUARD = 0x00001000, // faction will attack players that were involved in PvP combats

View file

@ -21,6 +21,7 @@
#include "MapManager.h" #include "MapManager.h"
#include "DestinationHolder.h" #include "DestinationHolder.h"
#include "Unit.h"
#include <cmath> #include <cmath>

View file

@ -522,7 +522,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
// Spawn if necessary (loaded grids only) // Spawn if necessary (loaded grids only)
Map* map = const_cast<Map*>(MapManager::Instance().CreateBaseMap(data->mapid)); Map* map = const_cast<Map*>(MapManager::Instance().CreateBaseMap(data->mapid));
// We use spawn coords to spawn // We use spawn coords to spawn
if(!map->Instanceable() && !map->IsRemovalGrid(data->posX,data->posY)) if(!map->Instanceable() && map->IsLoaded(data->posX,data->posY))
{ {
Creature* pCreature = new Creature; Creature* pCreature = new Creature;
//sLog.outDebug("Spawning creature %u",*itr); //sLog.outDebug("Spawning creature %u",*itr);
@ -555,7 +555,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
// this base map checked as non-instanced and then only existed // this base map checked as non-instanced and then only existed
Map* map = const_cast<Map*>(MapManager::Instance().CreateBaseMap(data->mapid)); Map* map = const_cast<Map*>(MapManager::Instance().CreateBaseMap(data->mapid));
// We use current coords to unspawn, not spawn coords since creature can have changed grid // We use current coords to unspawn, not spawn coords since creature can have changed grid
if(!map->Instanceable() && !map->IsRemovalGrid(data->posX, data->posY)) if(!map->Instanceable() && map->IsLoaded(data->posX, data->posY))
{ {
GameObject* pGameobject = new GameObject; GameObject* pGameobject = new GameObject;
//sLog.outDebug("Spawning gameobject %u", *itr); //sLog.outDebug("Spawning gameobject %u", *itr);

View file

@ -1596,7 +1596,7 @@ InstanceGroupBind* Group::GetBoundInstance(Player* player)
InstanceGroupBind* Group::GetBoundInstance(Map* aMap) InstanceGroupBind* Group::GetBoundInstance(Map* aMap)
{ {
// Currently spawn numbering not different from map difficulty // Currently spawn numbering not different from map difficulty
Difficulty difficulty = Difficulty(aMap->GetSpawnMode()); Difficulty difficulty = GetDifficulty(aMap->IsRaid());
// some instances only have one difficulty // some instances only have one difficulty
MapDifficulty const* mapDiff = GetMapDifficultyData(aMap->GetId(),difficulty); MapDifficulty const* mapDiff = GetMapDifficultyData(aMap->GetId(),difficulty);

View file

@ -996,6 +996,18 @@ bool Item::IsBindedNotWith( Player const* player ) const
} }
} }
void Item::AddToClientUpdateList()
{
if (Player* pl = GetOwner())
pl->GetMap()->AddUpdateObject(this);
}
void Item::RemoveFromClientUpdateList()
{
if (Player* pl = GetOwner())
pl->GetMap()->RemoveUpdateObject(this);
}
void Item::BuildUpdateData(UpdateDataMapType& update_players) void Item::BuildUpdateData(UpdateDataMapType& update_players)
{ {
if (Player* pl = GetOwner()) if (Player* pl = GetOwner())

View file

@ -313,6 +313,8 @@ class MANGOS_DLL_SPEC Item : public Object
bool IsPotion() const { return GetProto()->IsPotion(); } bool IsPotion() const { return GetProto()->IsPotion(); }
bool IsConjuredConsumable() const { return GetProto()->IsConjuredConsumable(); } bool IsConjuredConsumable() const { return GetProto()->IsConjuredConsumable(); }
void AddToClientUpdateList();
void RemoveFromClientUpdateList();
void BuildUpdateData(UpdateDataMapType& update_players); void BuildUpdateData(UpdateDataMapType& update_players);
private: private:
uint8 m_slot; uint8 m_slot;

View file

@ -697,6 +697,9 @@ void Map::Update(const uint32 &t_diff)
} }
} }
// Send world objects and item update field changes
SendObjectUpdates();
// Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load ! // Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load !
// This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended // This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended
if (!IsBattleGroundOrArena()) if (!IsBattleGroundOrArena())
@ -3415,3 +3418,25 @@ DynamicObject* Map::GetDynamicObject(uint64 guid)
{ {
return m_objectsStore.find<DynamicObject>(guid, (DynamicObject*)NULL); return m_objectsStore.find<DynamicObject>(guid, (DynamicObject*)NULL);
} }
void Map::SendObjectUpdates()
{
UpdateDataMapType update_players;
while(!i_objectsToClientUpdate.empty())
{
Object* obj = *i_objectsToClientUpdate.begin();
i_objectsToClientUpdate.erase(i_objectsToClientUpdate.begin());
if (!obj)
continue;
obj->BuildUpdateData(update_players);
}
WorldPacket packet; // here we allocate a std::vector with a size of 0x10000
for(UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter)
{
iter->second.BuildPacket(&packet);
iter->first->GetSession()->SendPacket(&packet);
packet.clear(); // clean the string
}
}

View file

@ -296,6 +296,12 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
return( !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL ); return( !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL );
} }
bool IsLoaded(float x, float y) const
{
GridPair p = MaNGOS::ComputeGridPair(x, y);
return loaded(p);
}
bool GetUnloadLock(const GridPair &p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); } bool GetUnloadLock(const GridPair &p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); }
void SetUnloadLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); } void SetUnloadLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); }
void LoadGrid(const Cell& cell, bool no_unload = false); void LoadGrid(const Cell& cell, bool no_unload = false);
@ -428,6 +434,16 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
DynamicObject* GetDynamicObject(uint64 guid); DynamicObject* GetDynamicObject(uint64 guid);
TypeUnorderedMapContainer<AllMapStoredObjectTypes>& GetObjectsStore() { return m_objectsStore; } TypeUnorderedMapContainer<AllMapStoredObjectTypes>& GetObjectsStore() { return m_objectsStore; }
void AddUpdateObject(Object *obj)
{
i_objectsToClientUpdate.insert(obj);
}
void RemoveUpdateObject(Object *obj)
{
i_objectsToClientUpdate.erase( obj );
}
private: private:
void LoadMapAndVMap(int gx, int gy); void LoadMapAndVMap(int gx, int gy);
void LoadVMap(int gx, int gy); void LoadVMap(int gx, int gy);
@ -472,6 +488,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
void setNGrid(NGridType* grid, uint32 x, uint32 y); void setNGrid(NGridType* grid, uint32 x, uint32 y);
void ScriptsProcess(); void ScriptsProcess();
void SendObjectUpdates();
std::set<Object *> i_objectsToClientUpdate;
protected: protected:
void SetUnloadReferenceLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); } void SetUnloadReferenceLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); }

View file

@ -167,7 +167,9 @@ Map* MapInstanced::CreateInstance(const uint32 mapId, Player * player)
// if no instanceId via group members or instance saves is found // if no instanceId via group members or instance saves is found
// the instance will be created for the first time // the instance will be created for the first time
NewInstanceId = MapManager::Instance().GenerateInstanceId(); NewInstanceId = MapManager::Instance().GenerateInstanceId();
map = CreateInstance(NewInstanceId, NULL, player->GetDifficulty(IsRaid()));
Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid());
map = CreateInstance(NewInstanceId, NULL, diff);
} }
} }

View file

@ -21,7 +21,6 @@
#include "Policies/SingletonImp.h" #include "Policies/SingletonImp.h"
#include "Database/DatabaseEnv.h" #include "Database/DatabaseEnv.h"
#include "Log.h" #include "Log.h"
#include "ObjectAccessor.h"
#include "Transports.h" #include "Transports.h"
#include "GridDefines.h" #include "GridDefines.h"
#include "MapInstanced.h" #include "MapInstanced.h"
@ -268,7 +267,6 @@ MapManager::Update(uint32 diff)
iter->second->Update(i_timer.GetCurrent()); iter->second->Update(i_timer.GetCurrent());
} }
ObjectAccessor::Instance().Update(i_timer.GetCurrent());
for (TransportSet::iterator iter = m_Transports.begin(); iter != m_Transports.end(); ++iter) for (TransportSet::iterator iter = m_Transports.begin(); iter != m_Transports.end(); ++iter)
(*iter)->Update(i_timer.GetCurrent()); (*iter)->Update(i_timer.GetCurrent());

View file

@ -31,7 +31,6 @@
#include "UpdateMask.h" #include "UpdateMask.h"
#include "Util.h" #include "Util.h"
#include "MapManager.h" #include "MapManager.h"
#include "ObjectAccessor.h"
#include "Log.h" #include "Log.h"
#include "Transports.h" #include "Transports.h"
#include "TargetedMovementGenerator.h" #include "TargetedMovementGenerator.h"
@ -80,9 +79,6 @@ Object::Object( ) : m_PackGUID(sizeof(uint64)+1)
Object::~Object( ) Object::~Object( )
{ {
if(m_objectUpdated)
ObjectAccessor::Instance().RemoveUpdateObject(this);
if(m_uint32Values) if(m_uint32Values)
{ {
if(IsInWorld()) if(IsInWorld())
@ -744,10 +740,11 @@ void Object::ClearUpdateMask(bool remove)
if(m_uint32Values_mirror[index]!= m_uint32Values[index]) if(m_uint32Values_mirror[index]!= m_uint32Values[index])
m_uint32Values_mirror[index] = m_uint32Values[index]; m_uint32Values_mirror[index] = m_uint32Values[index];
} }
if(m_objectUpdated) if(m_objectUpdated)
{ {
if(remove) if(remove)
ObjectAccessor::Instance().RemoveUpdateObject(this); RemoveFromClientUpdateList();
m_objectUpdated = false; m_objectUpdated = false;
} }
} }
@ -801,7 +798,7 @@ void Object::SetInt32Value( uint16 index, int32 value )
{ {
if(!m_objectUpdated) if(!m_objectUpdated)
{ {
ObjectAccessor::Instance().AddUpdateObject(this); AddToClientUpdateList();
m_objectUpdated = true; m_objectUpdated = true;
} }
} }
@ -820,7 +817,7 @@ void Object::SetUInt32Value( uint16 index, uint32 value )
{ {
if(!m_objectUpdated) if(!m_objectUpdated)
{ {
ObjectAccessor::Instance().AddUpdateObject(this); AddToClientUpdateList();
m_objectUpdated = true; m_objectUpdated = true;
} }
} }
@ -839,7 +836,7 @@ void Object::SetUInt64Value( uint16 index, const uint64 &value )
{ {
if(!m_objectUpdated) if(!m_objectUpdated)
{ {
ObjectAccessor::Instance().AddUpdateObject(this); AddToClientUpdateList();
m_objectUpdated = true; m_objectUpdated = true;
} }
} }
@ -858,7 +855,7 @@ void Object::SetFloatValue( uint16 index, float value )
{ {
if(!m_objectUpdated) if(!m_objectUpdated)
{ {
ObjectAccessor::Instance().AddUpdateObject(this); AddToClientUpdateList();
m_objectUpdated = true; m_objectUpdated = true;
} }
} }
@ -884,7 +881,7 @@ void Object::SetByteValue( uint16 index, uint8 offset, uint8 value )
{ {
if(!m_objectUpdated) if(!m_objectUpdated)
{ {
ObjectAccessor::Instance().AddUpdateObject(this); AddToClientUpdateList();
m_objectUpdated = true; m_objectUpdated = true;
} }
} }
@ -910,7 +907,7 @@ void Object::SetUInt16Value( uint16 index, uint8 offset, uint16 value )
{ {
if(!m_objectUpdated) if(!m_objectUpdated)
{ {
ObjectAccessor::Instance().AddUpdateObject(this); AddToClientUpdateList();
m_objectUpdated = true; m_objectUpdated = true;
} }
} }
@ -979,7 +976,7 @@ void Object::SetFlag( uint16 index, uint32 newFlag )
{ {
if(!m_objectUpdated) if(!m_objectUpdated)
{ {
ObjectAccessor::Instance().AddUpdateObject(this); AddToClientUpdateList();
m_objectUpdated = true; m_objectUpdated = true;
} }
} }
@ -1000,7 +997,7 @@ void Object::RemoveFlag( uint16 index, uint32 oldFlag )
{ {
if(!m_objectUpdated) if(!m_objectUpdated)
{ {
ObjectAccessor::Instance().AddUpdateObject(this); AddToClientUpdateList();
m_objectUpdated = true; m_objectUpdated = true;
} }
} }
@ -1025,7 +1022,7 @@ void Object::SetByteFlag( uint16 index, uint8 offset, uint8 newFlag )
{ {
if(!m_objectUpdated) if(!m_objectUpdated)
{ {
ObjectAccessor::Instance().AddUpdateObject(this); AddToClientUpdateList();
m_objectUpdated = true; m_objectUpdated = true;
} }
} }
@ -1050,7 +1047,7 @@ void Object::RemoveByteFlag( uint16 index, uint8 offset, uint8 oldFlag )
{ {
if(!m_objectUpdated) if(!m_objectUpdated)
{ {
ObjectAccessor::Instance().AddUpdateObject(this); AddToClientUpdateList();
m_objectUpdated = true; m_objectUpdated = true;
} }
} }
@ -1079,6 +1076,24 @@ void Object::BuildUpdateDataForPlayer(Player* pl, UpdateDataMapType& update_play
BuildValuesUpdateBlockForPlayer(&iter->second, iter->first); BuildValuesUpdateBlockForPlayer(&iter->second, iter->first);
} }
void Object::AddToClientUpdateList()
{
sLog.outError("Unexpected call of Object::AddToClientUpdateList for object (TypeId: %u Update fields: %u)",GetTypeId(), m_valuesCount);
ASSERT(false);
}
void Object::RemoveFromClientUpdateList()
{
sLog.outError("Unexpected call of Object::RemoveFromClientUpdateList for object (TypeId: %u Update fields: %u)",GetTypeId(), m_valuesCount);
ASSERT(false);
}
void Object::BuildUpdateData( UpdateDataMapType& update_players )
{
sLog.outError("Unexpected call of Object::BuildUpdateData for object (TypeId: %u Update fields: %u)",GetTypeId(), m_valuesCount);
ASSERT(false);
}
WorldObject::WorldObject() WorldObject::WorldObject()
: m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL), : m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL),
m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f), m_currMap(NULL) m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f), m_currMap(NULL)
@ -1871,6 +1886,16 @@ void WorldObject::UpdateObjectVisibility()
GetMap()->UpdateObjectVisibility(this, cell, p); GetMap()->UpdateObjectVisibility(this, cell, p);
} }
void WorldObject::AddToClientUpdateList()
{
GetMap()->AddUpdateObject(this);
}
void WorldObject::RemoveFromClientUpdateList()
{
GetMap()->RemoveUpdateObject(this);
}
struct WorldObjectChangeAccumulator struct WorldObjectChangeAccumulator
{ {
UpdateDataMapType &i_updateDatas; UpdateDataMapType &i_updateDatas;

View file

@ -124,7 +124,7 @@ class MANGOS_DLL_SPEC Object
m_inWorld = true; m_inWorld = true;
// synchronize values mirror with values array (changes will send in updatecreate opcode any way // synchronize values mirror with values array (changes will send in updatecreate opcode any way
ClearUpdateMask(true); ClearUpdateMask(false); // false - we can't have update dat in update queue before adding to world
} }
virtual void RemoveFromWorld() virtual void RemoveFromWorld()
{ {
@ -148,7 +148,11 @@ class MANGOS_DLL_SPEC Object
virtual void BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) const; virtual void BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) const;
void SendCreateUpdateToPlayer(Player* player); void SendCreateUpdateToPlayer(Player* player);
virtual void BuildUpdateData(UpdateDataMapType& update_players) =0; // must be overwrite in appropriate subclasses (WorldObject, Item currently), or will crash
virtual void AddToClientUpdateList();
virtual void RemoveFromClientUpdateList();
virtual void BuildUpdateData(UpdateDataMapType& update_players);
void BuildValuesUpdateBlockForPlayer( UpdateData *data, Player *target ) const; void BuildValuesUpdateBlockForPlayer( UpdateData *data, Player *target ) const;
void BuildOutOfRangeUpdateBlock( UpdateData *data ) const; void BuildOutOfRangeUpdateBlock( UpdateData *data ) const;
void BuildMovementUpdateBlock( UpdateData * data, uint32 flags = 0 ) const; void BuildMovementUpdateBlock( UpdateData * data, uint32 flags = 0 ) const;
@ -308,6 +312,7 @@ class MANGOS_DLL_SPEC Object
virtual void _SetUpdateBits(UpdateMask *updateMask, Player *target) const; virtual void _SetUpdateBits(UpdateMask *updateMask, Player *target) const;
virtual void _SetCreateBits(UpdateMask *updateMask, Player *target) const; virtual void _SetCreateBits(UpdateMask *updateMask, Player *target) const;
void BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2 ) const; void BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2 ) const;
void BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, UpdateMask *updateMask, Player *target ) const; void BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, UpdateMask *updateMask, Player *target ) const;
void BuildUpdateDataForPlayer(Player* pl, UpdateDataMapType& update_players); void BuildUpdateDataForPlayer(Player* pl, UpdateDataMapType& update_players);
@ -494,6 +499,8 @@ class MANGOS_DLL_SPEC WorldObject : public Object
//this function should be removed in nearest time... //this function should be removed in nearest time...
Map const* GetBaseMap() const; Map const* GetBaseMap() const;
void AddToClientUpdateList();
void RemoveFromClientUpdateList();
void BuildUpdateData(UpdateDataMapType &); void BuildUpdateData(UpdateDataMapType &);
Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime); Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime);

View file

@ -331,31 +331,6 @@ ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool insignia)
return bones; return bones;
} }
void
ObjectAccessor::Update(uint32 diff)
{
UpdateDataMapType update_players;
{
Guard guard(i_updateGuard);
while(!i_objects.empty())
{
Object* obj = *i_objects.begin();
i_objects.erase(i_objects.begin());
if (!obj)
continue;
obj->BuildUpdateData(update_players);
}
}
WorldPacket packet; // here we allocate a std::vector with a size of 0x10000
for(UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter)
{
iter->second.BuildPacket(&packet);
iter->first->GetSession()->SendPacket(&packet);
packet.clear(); // clean the string
}
}
/// Define the static member of HashMapHolder /// Define the static member of HashMapHolder
template <class T> UNORDERED_MAP< uint64, T* > HashMapHolder<T>::m_objectMap; template <class T> UNORDERED_MAP< uint64, T* > HashMapHolder<T>::m_objectMap;

View file

@ -152,27 +152,10 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor,
void RemoveObject(Player *pl) void RemoveObject(Player *pl)
{ {
HashMapHolder<Player>::Remove(pl); HashMapHolder<Player>::Remove(pl);
Guard guard(i_updateGuard);
i_objects.erase((Object *)pl);
} }
void SaveAllPlayers(); void SaveAllPlayers();
void AddUpdateObject(Object *obj)
{
Guard guard(i_updateGuard);
i_objects.insert(obj);
}
void RemoveUpdateObject(Object *obj)
{
Guard guard(i_updateGuard);
i_objects.erase( obj );
}
void Update(uint32 diff);
Corpse* GetCorpseForPlayerGUID(uint64 guid); Corpse* GetCorpseForPlayerGUID(uint64 guid);
void RemoveCorpse(Corpse *corpse); void RemoveCorpse(Corpse *corpse);
void AddCorpse(Corpse* corpse); void AddCorpse(Corpse* corpse);
@ -206,9 +189,7 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor,
typedef ACE_Thread_Mutex LockType; typedef ACE_Thread_Mutex LockType;
typedef MaNGOS::GeneralLock<LockType > Guard; typedef MaNGOS::GeneralLock<LockType > Guard;
std::set<Object *> i_objects;
LockType i_playerGuard; LockType i_playerGuard;
LockType i_updateGuard;
LockType i_corpseGuard; LockType i_corpseGuard;
}; };

View file

@ -1041,6 +1041,14 @@ void ObjectMgr::LoadCreatures()
if(cInfo->HeroicEntry) if(cInfo->HeroicEntry)
heroicCreatures.insert(cInfo->HeroicEntry); heroicCreatures.insert(cInfo->HeroicEntry);
// build single time for check spawnmask
std::map<uint32,uint32> spawnMasks;
for(uint32 i = 0; i < sMapStore.GetNumRows(); ++i)
if(sMapStore.LookupEntry(i))
for(int k = 0; k < MAX_DIFFICULTY; ++k)
if (GetMapDifficultyData(i,Difficulty(k)))
spawnMasks[i] |= (1 << k);
barGoLink bar(result->GetRowCount()); barGoLink bar(result->GetRowCount());
do do
@ -1080,6 +1088,16 @@ void ObjectMgr::LoadCreatures()
int16 gameEvent = fields[18].GetInt16(); int16 gameEvent = fields[18].GetInt16();
int16 PoolId = fields[19].GetInt16(); int16 PoolId = fields[19].GetInt16();
MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid);
if(!mapEntry)
{
sLog.outErrorDb("Table `creature` have creature (GUID: %u) that spawned at not existed map (Id: %u), skipped.",guid, data.mapid );
continue;
}
if (data.spawnMask & ~spawnMasks[data.mapid])
sLog.outErrorDb("Table `creature` have creature (GUID: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u).",guid, data.spawnMask, data.mapid );
if(heroicCreatures.find(data.id)!=heroicCreatures.end()) if(heroicCreatures.find(data.id)!=heroicCreatures.end())
{ {
sLog.outErrorDb("Table `creature` have creature (GUID: %u) that listed as heroic template (entry: %u) in `creature_template`, skipped.",guid, data.id ); sLog.outErrorDb("Table `creature` have creature (GUID: %u) that listed as heroic template (entry: %u) in `creature_template`, skipped.",guid, data.id );
@ -1103,8 +1121,7 @@ void ObjectMgr::LoadCreatures()
if(cInfo->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND) if(cInfo->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
{ {
MapEntry const* map = sMapStore.LookupEntry(data.mapid); if(!mapEntry || !mapEntry->IsDungeon())
if(!map || !map->IsDungeon())
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`flags_extra` including CREATURE_FLAG_EXTRA_INSTANCE_BIND but creature are not in instance.",guid,data.id); sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`flags_extra` including CREATURE_FLAG_EXTRA_INSTANCE_BIND but creature are not in instance.",guid,data.id);
} }
@ -1209,6 +1226,14 @@ void ObjectMgr::LoadGameobjects()
return; return;
} }
// build single time for check spawnmask
std::map<uint32,uint32> spawnMasks;
for(uint32 i = 0; i < sMapStore.GetNumRows(); ++i)
if(sMapStore.LookupEntry(i))
for(int k = 0; k < MAX_DIFFICULTY; ++k)
if (GetMapDifficultyData(i,Difficulty(k)))
spawnMasks[i] |= (1 << k);
barGoLink bar(result->GetRowCount()); barGoLink bar(result->GetRowCount());
do do
@ -1259,6 +1284,16 @@ void ObjectMgr::LoadGameobjects()
data.rotation3 = fields[10].GetFloat(); data.rotation3 = fields[10].GetFloat();
data.spawntimesecs = fields[11].GetInt32(); data.spawntimesecs = fields[11].GetInt32();
MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid);
if(!mapEntry)
{
sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) that spawned at not existed map (Id: %u), skip", guid, data.id, data.mapid);
continue;
}
if (data.spawnMask & ~spawnMasks[data.mapid])
sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.mapid);
if (data.spawntimesecs == 0 && gInfo->IsDespawnAtAction()) if (data.spawntimesecs == 0 && gInfo->IsDespawnAtAction())
{ {
sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with `spawntimesecs` (0) value, but gameobejct marked as despawnable at action.", guid, data.id); sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with `spawntimesecs` (0) value, but gameobejct marked as despawnable at action.", guid, data.id);

View file

@ -1179,10 +1179,10 @@ void Pet::_LoadAuras(uint32 timediff)
// negative effects should continue counting down after logout // negative effects should continue counting down after logout
if (remaintime != -1 && !IsPositiveEffect(spellid, effindex)) if (remaintime != -1 && !IsPositiveEffect(spellid, effindex))
{ {
if(remaintime <= int32(timediff)) if (remaintime/IN_MILISECONDS <= int32(timediff))
continue; continue;
remaintime -= timediff; remaintime -= timediff*IN_MILISECONDS;
} }
// prevent wrong values of remaincharges // prevent wrong values of remaincharges

View file

@ -2072,24 +2072,10 @@ void Player::RegenerateHealth(uint32 diff)
ModifyHealth(int32(addvalue)); ModifyHealth(int32(addvalue));
} }
bool Player::CanInteractWithNPCs(bool alive) const Creature* Player::GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask)
{
if(alive && !isAlive())
return false;
if(isInFlight())
return false;
return true;
}
Creature*
Player::GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask)
{ {
// unit checks // unit checks
if (!guid) if (!guid || !IsInWorld() || isInFlight())
return NULL;
if(!IsInWorld())
return NULL; return NULL;
// exist (we need look pets also for some interaction (quest/etc) // exist (we need look pets also for some interaction (quest/etc)
@ -2097,23 +2083,23 @@ Player::GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask)
if (!unit) if (!unit)
return NULL; return NULL;
// player check
if(!CanInteractWithNPCs(!(unit->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_GHOST)))
return NULL;
// appropriate npc type // appropriate npc type
if(npcflagmask && !unit->HasFlag( UNIT_NPC_FLAGS, npcflagmask )) if (npcflagmask && !unit->HasFlag( UNIT_NPC_FLAGS, npcflagmask ))
return NULL; return NULL;
if (isAlive() && !unit->isAlive()) // if a dead unit should be able to talk - the creature must be alive and have special flags
if (!unit->isAlive())
return NULL;
if (isAlive() && unit->isInvisibleForAlive())
return NULL; return NULL;
// not allow interaction under control, but allow with own pets // not allow interaction under control, but allow with own pets
if(unit->GetCharmerGUID()) if (unit->GetCharmerGUID())
return NULL; return NULL;
// not enemy // not enemy
if( unit->IsHostileTo(this)) if (unit->IsHostileTo(this))
return NULL; return NULL;
// not unfriendly // not unfriendly
@ -14835,10 +14821,10 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff)
// negative effects should continue counting down after logout // negative effects should continue counting down after logout
if (remaintime != -1 && !IsPositiveEffect(spellid, effindex)) if (remaintime != -1 && !IsPositiveEffect(spellid, effindex))
{ {
if(remaintime <= int32(timediff)) if (remaintime/IN_MILISECONDS <= int32(timediff))
continue; continue;
remaintime -= timediff; remaintime -= timediff*IN_MILISECONDS;
} }
// prevent wrong values of remaincharges // prevent wrong values of remaincharges

View file

@ -1046,7 +1046,6 @@ class MANGOS_DLL_SPEC Player : public Unit
void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time); void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time);
Creature* GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask); Creature* GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask);
bool CanInteractWithNPCs(bool alive = true) const;
GameObject* GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes type) const; GameObject* GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes type) const;
void UpdateVisibilityForPlayer(); void UpdateVisibilityForPlayer();

View file

@ -243,7 +243,7 @@ bool PoolGroup<Creature>::Spawn1Object(uint32 guid)
// Spawn if necessary (loaded grids only) // Spawn if necessary (loaded grids only)
Map* map = const_cast<Map*>(MapManager::Instance().CreateBaseMap(data->mapid)); Map* map = const_cast<Map*>(MapManager::Instance().CreateBaseMap(data->mapid));
// We use spawn coords to spawn // We use spawn coords to spawn
if (!map->Instanceable() && !map->IsRemovalGrid(data->posX, data->posY)) if (!map->Instanceable() && map->IsLoaded(data->posX, data->posY))
{ {
Creature* pCreature = new Creature; Creature* pCreature = new Creature;
//sLog.outDebug("Spawning creature %u",guid); //sLog.outDebug("Spawning creature %u",guid);
@ -273,7 +273,7 @@ bool PoolGroup<GameObject>::Spawn1Object(uint32 guid)
// this base map checked as non-instanced and then only existed // this base map checked as non-instanced and then only existed
Map* map = const_cast<Map*>(MapManager::Instance().CreateBaseMap(data->mapid)); Map* map = const_cast<Map*>(MapManager::Instance().CreateBaseMap(data->mapid));
// We use current coords to unspawn, not spawn coords since creature can have changed grid // We use current coords to unspawn, not spawn coords since creature can have changed grid
if (!map->Instanceable() && !map->IsRemovalGrid(data->posX, data->posY)) if (!map->Instanceable() && map->IsLoaded(data->posX, data->posY))
{ {
GameObject* pGameobject = new GameObject; GameObject* pGameobject = new GameObject;
//sLog.outDebug("Spawning gameobject %u", guid); //sLog.outDebug("Spawning gameobject %u", guid);

View file

@ -132,6 +132,9 @@ enum __QuestFlags
QUEST_FLAGS_AUTO_REWARDED = 0x00000400, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side. QUEST_FLAGS_AUTO_REWARDED = 0x00000400, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side.
QUEST_FLAGS_TBC_RACES = 0x00000800, // Not used currently: Blood elf/Draenei starting zone quests QUEST_FLAGS_TBC_RACES = 0x00000800, // Not used currently: Blood elf/Draenei starting zone quests
QUEST_FLAGS_DAILY = 0x00001000, // Used to know quest is Daily one QUEST_FLAGS_DAILY = 0x00001000, // Used to know quest is Daily one
QUEST_FLAGS_UNK3 = 0x00002000,
QUEST_FLAGS_UNK4 = 0x00004000, // ? Membership Card Renewal
QUEST_FLAGS_WEEKLY = 0x00008000, // Not used currently: Weekly quests
// Mangos flags for set SpecialFlags in DB if required but used only at server // Mangos flags for set SpecialFlags in DB if required but used only at server
QUEST_MANGOS_FLAGS_REPEATABLE = 0x010000, // Set by 1 in SpecialFlags from DB QUEST_MANGOS_FLAGS_REPEATABLE = 0x010000, // Set by 1 in SpecialFlags from DB

View file

@ -1883,26 +1883,30 @@ enum CreatureFamily
enum CreatureTypeFlags enum CreatureTypeFlags
{ {
CREATURE_TYPEFLAGS_TAMEABLE = 0x00001, //tameable by any hunter CREATURE_TYPEFLAGS_TAMEABLE = 0x000001, // Tameable by any hunter
CREATURE_TYPEFLAGS_UNK2 = 0x00002, //? Related to spirits/ghosts in any form? Allow gossip interaction if player is also ghost? Visibility? CREATURE_TYPEFLAGS_GHOST_VISIBLE = 0x000002, // Creatures which can _also_ be seen when player is a ghost
CREATURE_TYPEFLAGS_UNK3 = 0x00004, CREATURE_TYPEFLAGS_UNK3 = 0x000004,
CREATURE_TYPEFLAGS_UNK4 = 0x00008, CREATURE_TYPEFLAGS_UNK4 = 0x000008,
CREATURE_TYPEFLAGS_UNK5 = 0x00010, CREATURE_TYPEFLAGS_UNK5 = 0x000010,
CREATURE_TYPEFLAGS_UNK6 = 0x00020, CREATURE_TYPEFLAGS_UNK6 = 0x000020,
CREATURE_TYPEFLAGS_UNK7 = 0x00040, CREATURE_TYPEFLAGS_UNK7 = 0x000040,
CREATURE_TYPEFLAGS_UNK8 = 0x00080, CREATURE_TYPEFLAGS_UNK8 = 0x000080,
CREATURE_TYPEFLAGS_HERBLOOT = 0x00100, //can be looted by herbalist CREATURE_TYPEFLAGS_HERBLOOT = 0x000100, // Can be looted by herbalist
CREATURE_TYPEFLAGS_MININGLOOT = 0x00200, //can be looted by miner CREATURE_TYPEFLAGS_MININGLOOT = 0x000200, // Can be looted by miner
CREATURE_TYPEFLAGS_UNK11 = 0x00400, CREATURE_TYPEFLAGS_UNK11 = 0x000400,
CREATURE_TYPEFLAGS_UNK12 = 0x00800, //? Related to mounts in some way. If mounted, fight mounted, mount appear as independant when rider dies? CREATURE_TYPEFLAGS_UNK12 = 0x000800, // ? Related to mounts in some way. If mounted, fight mounted, mount appear as independant when rider dies?
CREATURE_TYPEFLAGS_UNK13 = 0x01000, //? Can aid any player in combat if in range? CREATURE_TYPEFLAGS_UNK13 = 0x001000, // ? Can aid any player in combat if in range?
CREATURE_TYPEFLAGS_UNK14 = 0x02000, CREATURE_TYPEFLAGS_UNK14 = 0x002000,
CREATURE_TYPEFLAGS_UNK15 = 0x04000, //? Possibly not in use CREATURE_TYPEFLAGS_UNK15 = 0x004000, // ? Possibly not in use
CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x08000, //can be looted by engineer CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x008000, // Can be looted by engineer
CREATURE_TYPEFLAGS_EXOTIC = 0x10000, //can be tamed by hunter as exotic pet CREATURE_TYPEFLAGS_EXOTIC = 0x010000, // Can be tamed by hunter as exotic pet
CREATURE_TYPEFLAGS_UNK18 = 0x20000, //? Related to veichles/pvp? CREATURE_TYPEFLAGS_UNK18 = 0x020000, // ? Related to vehicles/pvp?
CREATURE_TYPEFLAGS_UNK19 = 0x40000, //? Related to veichle/siege weapons? CREATURE_TYPEFLAGS_UNK19 = 0x040000, // ? Related to vehicle/siege weapons?
CREATURE_TYPEFLAGS_UNK20 = 0x80000 CREATURE_TYPEFLAGS_UNK20 = 0x080000,
CREATURE_TYPEFLAGS_UNK21 = 0x100000,
CREATURE_TYPEFLAGS_UNK22 = 0x200000,
CREATURE_TYPEFLAGS_UNK23 = 0x400000,
CREATURE_TYPEFLAGS_UNK24 = 0x800000 // ? First seen in 3.2.2. Related to banner/backpack of creature/companion?
}; };
enum CreatureEliteType enum CreatureEliteType

View file

@ -3930,7 +3930,7 @@ SpellCastResult Spell::CheckCast(bool strict)
if(m_spellInfo->TargetAuraStateNot && target->HasAuraState(AuraState(m_spellInfo->TargetAuraStateNot))) if(m_spellInfo->TargetAuraStateNot && target->HasAuraState(AuraState(m_spellInfo->TargetAuraStateNot)))
return SPELL_FAILED_TARGET_AURASTATE; return SPELL_FAILED_TARGET_AURASTATE;
if (IsDeathOnlySpell(m_spellInfo) && target->isAlive()) if (!m_IsTriggeredSpell && IsDeathOnlySpell(m_spellInfo) && target->isAlive())
return SPELL_FAILED_TARGET_NOT_DEAD; return SPELL_FAILED_TARGET_NOT_DEAD;
// Target aura req check if need // Target aura req check if need
@ -4124,8 +4124,7 @@ SpellCastResult Spell::CheckCast(bool strict)
(m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[j] != TARGET_SELF) || (m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[j] != TARGET_SELF) ||
m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES ||
m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES || m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ||
// Check possible in DB targets only for spells with no implicit spell focus m_spellInfo->EffectImplicitTargetA[j] == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT)
(m_spellInfo->EffectImplicitTargetA[j] == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT && !m_spellInfo->RequiresSpellFocus))
{ {
SpellScriptTargetBounds bounds = spellmgr.GetSpellScriptTargetBounds(m_spellInfo->Id); SpellScriptTargetBounds bounds = spellmgr.GetSpellScriptTargetBounds(m_spellInfo->Id);
@ -4241,6 +4240,11 @@ SpellCastResult Spell::CheckCast(bool strict)
} }
//Missing DB Entry or targets for this spellEffect. //Missing DB Entry or targets for this spellEffect.
else else
{
/* For TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT makes DB targets optional not required for now
* TODO: Makes more research for this target type
*/
if (m_spellInfo->EffectImplicitTargetA[j] != TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT)
{ {
// not report target not existence for triggered spells // not report target not existence for triggered spells
if(m_triggeredByAuraSpell || m_IsTriggeredSpell) if(m_triggeredByAuraSpell || m_IsTriggeredSpell)
@ -4251,6 +4255,7 @@ SpellCastResult Spell::CheckCast(bool strict)
} }
} }
} }
}
if(!m_IsTriggeredSpell) if(!m_IsTriggeredSpell)
{ {

View file

@ -572,7 +572,7 @@ Aura* CreateAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoi
Unit* Aura::GetCaster() const Unit* Aura::GetCaster() const
{ {
if(m_caster_guid==m_target->GetGUID()) if(m_caster_guid == m_target->GetGUID())
return m_target; return m_target;
//return ObjectAccessor::GetUnit(*m_target,m_caster_guid); //return ObjectAccessor::GetUnit(*m_target,m_caster_guid);
@ -1450,10 +1450,10 @@ void Aura::HandleAddTargetTrigger(bool apply, bool /*Real*/)
void Aura::TriggerSpell() void Aura::TriggerSpell()
{ {
Unit* caster = GetCaster(); const uint64& casterGUID = GetCasterGUID();
Unit* target = GetTriggerTarget(); Unit* target = GetTriggerTarget();
if(!caster || !target) if(!casterGUID || !target)
return; return;
// generic casting code with custom spells and target/caster customs // generic casting code with custom spells and target/caster customs
@ -1479,9 +1479,9 @@ void Aura::TriggerSpell()
case 17949: case 17949:
case 27252: case 27252:
{ {
if (caster->GetTypeId()!=TYPEID_PLAYER) if (target->GetTypeId() != TYPEID_PLAYER)
return; return;
Item* item = ((Player*)caster)->GetWeaponForAttack(BASE_ATTACK); Item* item = ((Player*)target)->GetWeaponForAttack(BASE_ATTACK);
if (!item) if (!item)
return; return;
uint32 enchant_id = 0; uint32 enchant_id = 0;
@ -1496,10 +1496,10 @@ void Aura::TriggerSpell()
return; return;
} }
// remove old enchanting before applying new // remove old enchanting before applying new
((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false); ((Player*)target)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false);
item->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, m_modifier.periodictime+1000, 0); item->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, m_modifier.periodictime+1000, 0);
// add new enchanting // add new enchanting
((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true); ((Player*)target)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true);
return; return;
} }
// // Periodic Mana Burn // // Periodic Mana Burn
@ -1542,14 +1542,13 @@ void Aura::TriggerSpell()
// Restoration // Restoration
case 23493: case 23493:
{ {
int32 heal = caster->GetMaxHealth() / 10; int32 heal = target->GetMaxHealth() / 10;
caster->DealHeal(caster, heal, auraSpellInfo); target->DealHeal(target, heal, auraSpellInfo);
int32 mana = caster->GetMaxPower(POWER_MANA); if (int32 mana = target->GetMaxPower(POWER_MANA))
if (mana)
{ {
mana /= 10; mana /= 10;
caster->EnergizeBySpell(caster, 23493, mana, POWER_MANA); target->EnergizeBySpell(target, 23493, mana, POWER_MANA);
} }
return; return;
} }
@ -1579,7 +1578,7 @@ void Aura::TriggerSpell()
case 25371: case 25371:
{ {
int32 bpDamage = target->GetMaxHealth()*10/100; int32 bpDamage = target->GetMaxHealth()*10/100;
caster->CastCustomSpell(target, 25373, &bpDamage, NULL, NULL, true, NULL, this); target->CastCustomSpell(target, 25373, &bpDamage, NULL, NULL, true, NULL, this, casterGUID);
return; return;
} }
// // Pain Spike // // Pain Spike
@ -1606,7 +1605,7 @@ void Aura::TriggerSpell()
case 27808: case 27808:
{ {
int32 bpDamage = target->GetMaxHealth()*26/100; int32 bpDamage = target->GetMaxHealth()*26/100;
caster->CastCustomSpell(target, 29879, &bpDamage, NULL, NULL, true, NULL, this); target->CastCustomSpell(target, 29879, &bpDamage, NULL, NULL, true, NULL, this, casterGUID);
return; return;
} }
// // Detonate Mana // // Detonate Mana
@ -1657,6 +1656,9 @@ void Aura::TriggerSpell()
// Extract Gas // Extract Gas
case 30427: case 30427:
{ {
Unit* caster = GetCaster();
if (!caster)
return;
// move loot to player inventory and despawn target // move loot to player inventory and despawn target
if(caster->GetTypeId() ==TYPEID_PLAYER && if(caster->GetTypeId() ==TYPEID_PLAYER &&
target->GetTypeId() == TYPEID_UNIT && target->GetTypeId() == TYPEID_UNIT &&
@ -1700,13 +1702,18 @@ void Aura::TriggerSpell()
case 31373: case 31373:
{ {
// Summon Elemental after create item // Summon Elemental after create item
caster->SummonCreature(17870, 0, 0, 0, caster->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0); target->SummonCreature(17870, 0, 0, 0, target->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0);
return; return;
} }
// // Bloodmyst Tesla // // Bloodmyst Tesla
// case 31611: break; // case 31611: break;
// // Doomfire // Doomfire
// case 31944: break; case 31944:
{
int32 damage = m_modifier.m_amount * ((float)(GetAuraDuration() + m_modifier.periodictime) / GetAuraMaxDuration());
target->CastCustomSpell(target, 31969, &damage, NULL, NULL, true, NULL, this, casterGUID);
return;
}
// // Teleport Test // // Teleport Test
// case 32236: break; // case 32236: break;
// // Earthquake // // Earthquake
@ -1722,9 +1729,9 @@ void Aura::TriggerSpell()
{ {
// cast 24 spells 34269-34289, 34314-34316 // cast 24 spells 34269-34289, 34314-34316
for(uint32 spell_id = 34269; spell_id != 34290; ++spell_id) for(uint32 spell_id = 34269; spell_id != 34290; ++spell_id)
caster->CastSpell(m_target, spell_id, true); target->CastSpell(target, spell_id, true, NULL, this, casterGUID);
for(uint32 spell_id = 34314; spell_id != 34317; ++spell_id) for(uint32 spell_id = 34314; spell_id != 34317; ++spell_id)
caster->CastSpell(m_target, spell_id, true); target->CastSpell(target, spell_id, true, NULL, this, casterGUID);
return; return;
} }
// // Gravity Lapse // // Gravity Lapse
@ -1815,7 +1822,10 @@ void Aura::TriggerSpell()
if(m_target->GetTypeId() != TYPEID_UNIT) if(m_target->GetTypeId() != TYPEID_UNIT)
return; return;
caster->CastSpell(caster, 38495, true); if (Unit* caster = GetCaster())
caster->CastSpell(caster, 38495, true, NULL, this);
else
return;
Creature* creatureTarget = (Creature*)m_target; Creature* creatureTarget = (Creature*)m_target;
@ -2073,7 +2083,7 @@ void Aura::TriggerSpell()
bool all = true; bool all = true;
for(int i = 0; i < MAX_TOTEM; ++i) for(int i = 0; i < MAX_TOTEM; ++i)
{ {
if(!caster->m_TotemSlot[i]) if(!target->m_TotemSlot[i])
{ {
all = false; all = false;
break; break;
@ -2081,9 +2091,9 @@ void Aura::TriggerSpell()
} }
if(all) if(all)
caster->CastSpell(caster, 38437, true); target->CastSpell(target, 38437, true, NULL, this);
else else
caster->RemoveAurasDueToSpell(38437); target->RemoveAurasDueToSpell(38437);
return; return;
} }
default: default:
@ -2113,14 +2123,14 @@ void Aura::TriggerSpell()
// 2) maybe aura must be replace by new with accumulative stat mods instead stacking // 2) maybe aura must be replace by new with accumulative stat mods instead stacking
// prevent cast by triggered auras // prevent cast by triggered auras
if(m_caster_guid == m_target->GetGUID()) if(casterGUID == target->GetGUID())
return; return;
// stop triggering after each affected stats lost > 90 // stop triggering after each affected stats lost > 90
int32 intelectLoss = 0; int32 intelectLoss = 0;
int32 spiritLoss = 0; int32 spiritLoss = 0;
Unit::AuraList const& mModStat = m_target->GetAurasByType(SPELL_AURA_MOD_STAT); Unit::AuraList const& mModStat = target->GetAurasByType(SPELL_AURA_MOD_STAT);
for(Unit::AuraList::const_iterator i = mModStat.begin(); i != mModStat.end(); ++i) for(Unit::AuraList::const_iterator i = mModStat.begin(); i != mModStat.end(); ++i)
{ {
if ((*i)->GetId() == 1010) if ((*i)->GetId() == 1010)
@ -2137,47 +2147,52 @@ void Aura::TriggerSpell()
if(intelectLoss <= -90 && spiritLoss <= -90) if(intelectLoss <= -90 && spiritLoss <= -90)
return; return;
caster = target;
break; break;
} }
// Mana Tide // Mana Tide
case 16191: case 16191:
{ {
caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this); target->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this);
return; return;
} }
// Ground Slam // Ground Slam
case 33525: case 33525:
target->CastSpell(target, trigger_spell_id, true); target->CastSpell(target, trigger_spell_id, true, NULL, this, casterGUID);
return; return;
// Beacon of Light // Beacon of Light
case 53563: case 53563:
// original caster must be target (beacon) // original caster must be target (beacon)
m_target->CastSpell(m_target,trigger_spell_id,true,NULL,this,m_target->GetGUID()); target->CastSpell(target, trigger_spell_id, true, NULL, this, target->GetGUID());
return; return;
} }
} }
// All ok cast by default case // All ok cast by default case
if(triggeredSpellInfo) if(triggeredSpellInfo)
caster->CastSpell(target, triggeredSpellInfo, true, 0, this); target->CastSpell(target, triggeredSpellInfo, true, NULL, this, casterGUID);
else if(target->GetTypeId()!=TYPEID_UNIT || !Script->EffectDummyCreature(caster, GetId(), GetEffIndex(), (Creature*)target)) else
{
if (Unit* caster = GetCaster())
{
if(target->GetTypeId() != TYPEID_UNIT || !Script->EffectDummyCreature(caster, GetId(), GetEffIndex(), (Creature*)target))
sLog.outError("Aura::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex()); sLog.outError("Aura::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex());
}
}
} }
void Aura::TriggerSpellWithValue() void Aura::TriggerSpellWithValue()
{ {
Unit* caster = GetCaster(); const uint64& casterGUID = GetCasterGUID();
Unit* target = GetTriggerTarget(); Unit* target = GetTriggerTarget();
if(!caster || !target) if(!casterGUID || !target)
return; return;
// generic casting code with custom spells and target/caster customs // generic casting code with custom spells and target/caster customs
uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex]; uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
int32 basepoints0 = this->GetModifier()->m_amount; int32 basepoints0 = this->GetModifier()->m_amount;
caster->CastCustomSpell(target, trigger_spell_id, &basepoints0, NULL, NULL, true, NULL, this); target->CastCustomSpell(target, trigger_spell_id, &basepoints0, NULL, NULL, true, NULL, this, casterGUID);
} }
/*********************************************************/ /*********************************************************/
@ -2457,6 +2472,16 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
m_target->PlayDirectSound(14972, (Player *)m_target); m_target->PlayDirectSound(14972, (Player *)m_target);
} }
return; return;
case 10848:
case 36978:
case 40131:
case 27978:
case 33900:
if (apply)
m_target->m_AuraFlags |= UNIT_AURAFLAG_ALIVE_INVISIBLE;
else
m_target->m_AuraFlags |= ~UNIT_AURAFLAG_ALIVE_INVISIBLE;
return;
} }
break; break;
} }
@ -6245,9 +6270,6 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real)
void Aura::PeriodicTick() void Aura::PeriodicTick()
{ {
if (!m_target->isAlive() != IsDeathOnlySpell(GetSpellProto()))
return;
switch(m_modifier.m_auraname) switch(m_modifier.m_auraname)
{ {
case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_DAMAGE:

View file

@ -2205,31 +2205,6 @@ void SpellMgr::LoadSpellScriptTarget()
continue; continue;
} }
// More checks on TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT
bool ok = true;
for (int i = 0; i < 3; ++i)
{
if (spellProto->EffectImplicitTargetA[i] == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT ||
spellProto->EffectImplicitTargetB[i] == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT)
{
if (spellProto->RequiresSpellFocus)
{
sLog.outErrorDb("Table `spell_script_target`: spellId %u for TargetEnty %u of type TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT is wrong because spell has implicit ReqSpellFocus %u.", spellId, targetEntry, spellProto->RequiresSpellFocus);
ok = false;
break;
}
if (type != SPELL_TARGET_TYPE_GAMEOBJECT)
{
sLog.outErrorDb("Table `spell_script_target`: spellId %u has target type TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT but target in table is creature (must be gameobject).", spellId);
ok = false;
break;
}
}
}
if (!ok)
continue;
// Checks by target type // Checks by target type
switch (type) switch (type)
{ {

View file

@ -104,6 +104,7 @@ Unit::Unit()
//m_AurasCheck = 2000; //m_AurasCheck = 2000;
//m_removeAuraTimer = 4; //m_removeAuraTimer = 4;
m_AurasUpdateIterator = m_Auras.end(); m_AurasUpdateIterator = m_Auras.end();
m_AuraFlags = 0;
m_Visibility = VISIBILITY_ON; m_Visibility = VISIBILITY_ON;
@ -5386,6 +5387,12 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 63106; triggered_spell_id = 63106;
break; break;
} }
// Glyph of Life Tap
case 63320:
{
triggered_spell_id = 63321;
break;
}
} }
break; break;
} }
@ -6276,8 +6283,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
case 10605: spellId = 45300; break; // Rank 4 case 10605: spellId = 45300; break; // Rank 4
case 25439: spellId = 45301; break; // Rank 5 case 25439: spellId = 45301; break; // Rank 5
case 25442: spellId = 45302; break; // Rank 6 case 25442: spellId = 45302; break; // Rank 6
case 49268: spellId = 49270; break; // Rank 7 case 49270: spellId = 49268; break; // Rank 7
case 49269: spellId = 49271; break; // Rank 8 case 49271: spellId = 49269; break; // Rank 8
default: default:
sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (LO)", procSpell->Id); sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (LO)", procSpell->Id);
return false; return false;
@ -9603,11 +9610,10 @@ bool Unit::isTargetableForAttack(bool inverseAlive /*=false*/) const
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE))
return false; return false;
// target is dead or has ghost-flag if ((isAlive() && !isInvisibleForAlive()) == inverseAlive)
if ((!isAlive() || (GetTypeId() == TYPEID_UNIT && ((Creature *)this)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_GHOST)) != inverseAlive)
return false; return false;
return IsInWorld() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/; return IsInWorld() && !hasUnitState(UNIT_STAT_DIED) && !isInFlight();
} }
int32 Unit::ModifyHealth(int32 dVal) int32 Unit::ModifyHealth(int32 dVal)
@ -9701,7 +9707,7 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
Map& _map = *u->GetMap(); Map& _map = *u->GetMap();
// Grid dead/alive checks // Grid dead/alive checks
if( u->GetTypeId()==TYPEID_PLAYER) if (u->GetTypeId()==TYPEID_PLAYER)
{ {
// non visible at grid for any stealth state // non visible at grid for any stealth state
if(!IsVisibleInGridForPlayer((Player *)u)) if(!IsVisibleInGridForPlayer((Player *)u))
@ -9719,15 +9725,15 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
} }
// always seen by owner // always seen by owner
if(GetCharmerOrOwnerGUID()==u->GetGUID()) if (GetCharmerOrOwnerGUID()==u->GetGUID())
return true; return true;
// always seen by far sight caster // always seen by far sight caster
if( u->GetTypeId()==TYPEID_PLAYER && ((Player*)u)->GetFarSight()==GetGUID()) if (u->GetTypeId()==TYPEID_PLAYER && ((Player*)u)->GetFarSight()==GetGUID())
return true; return true;
// different visible distance checks // different visible distance checks
if(u->isInFlight()) // what see player in flight if (u->isInFlight()) // what see player in flight
{ {
// use object grey distance for all (only see objects any way) // use object grey distance for all (only see objects any way)
if (!IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), is3dDistance)) if (!IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), is3dDistance))
@ -9766,6 +9772,10 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
return false; return false;
} }
if (u->isAlive() && isInvisibleForAlive())
if (u->GetTypeId() == TYPEID_PLAYER && !((Player *)u)->isGameMaster())
return false;
// Visible units, always are visible for all units, except for units under invisibility and phases // Visible units, always are visible for all units, except for units under invisibility and phases
if (m_Visibility == VISIBILITY_ON && u->m_invisibilityMask==0 && InSamePhase(u)) if (m_Visibility == VISIBILITY_ON && u->m_invisibilityMask==0 && InSamePhase(u))
return true; return true;
@ -10622,6 +10632,15 @@ bool Unit::isVisibleForInState( Player const* u, WorldObject const* viewPoint, b
return isVisibleForOrDetect(u, viewPoint, false, inVisibleList, false); return isVisibleForOrDetect(u, viewPoint, false, inVisibleList, false);
} }
/// returns true if creature can't be seen by alive units
bool Unit::isInvisibleForAlive() const
{
if (m_AuraFlags & UNIT_AURAFLAG_ALIVE_INVISIBLE)
return true;
// TODO: maybe spiritservices also have just an aura
return isSpiritService();
}
uint32 Unit::GetCreatureType() const uint32 Unit::GetCreatureType() const
{ {
if(GetTypeId() == TYPEID_PLAYER) if(GetTypeId() == TYPEID_PLAYER)

View file

@ -469,6 +469,12 @@ enum DamageEffectType
SELF_DAMAGE = 5 SELF_DAMAGE = 5
}; };
/// internal used flags for marking special auras - for example some dummy-auras
enum UnitAuraFlags
{
UNIT_AURAFLAG_ALIVE_INVISIBLE = 0x1, // aura which makes unit invisible for alive
};
enum UnitVisibility enum UnitVisibility
{ {
VISIBILITY_OFF = 0, // absolute, not detectable, GM-like, can see all other VISIBILITY_OFF = 0, // absolute, not detectable, GM-like, can see all other
@ -1329,6 +1335,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
bool isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const; bool isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const;
// function for low level grid visibility checks in player/creature cases // function for low level grid visibility checks in player/creature cases
virtual bool IsVisibleInGridForPlayer(Player* pl) const = 0; virtual bool IsVisibleInGridForPlayer(Player* pl) const = 0;
bool isInvisibleForAlive() const;
AuraList & GetSingleCastAuras() { return m_scAuras; } AuraList & GetSingleCastAuras() { return m_scAuras; }
AuraList const& GetSingleCastAuras() const { return m_scAuras; } AuraList const& GetSingleCastAuras() const { return m_scAuras; }
@ -1389,6 +1396,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
Aura* GetDummyAura(uint32 spell_id) const; Aura* GetDummyAura(uint32 spell_id) const;
uint32 m_AuraFlags;
uint32 GetDisplayId() { return GetUInt32Value(UNIT_FIELD_DISPLAYID); } uint32 GetDisplayId() { return GetUInt32Value(UNIT_FIELD_DISPLAYID); }
void SetDisplayId(uint32 modelId); void SetDisplayId(uint32 modelId);
uint32 GetNativeDisplayId() { return GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID); } uint32 GetNativeDisplayId() { return GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID); }

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "8677" #define REVISION_NR "8700"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__ #ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__ #define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_8596_01_characters_bugreport" #define REVISION_DB_CHARACTERS "required_8596_01_characters_bugreport"
#define REVISION_DB_MANGOS "required_8676_01_mangos_creature_template" #define REVISION_DB_MANGOS "required_8693_01_mangos_spell_proc_event"
#define REVISION_DB_REALMD "required_8332_01_realmd_realmcharacters" #define REVISION_DB_REALMD "required_8332_01_realmd_realmcharacters"
#endif // __REVISION_SQL_H__ #endif // __REVISION_SQL_H__