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,
`creature_ai_version` varchar(120) default NULL,
`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';
--
@ -18324,6 +18324,7 @@ INSERT INTO `spell_proc_event` VALUES
(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),
(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),
(64928, 0x00000000, 11, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0);
/*!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 \
8618_01_mangos_spell_proc_event.sql \
8676_01_mangos_creature_template.sql \
8688_01_mangos_creature_template.sql \
8693_01_mangos_spell_proc_event.sql \
README
## Additional files to include when running 'make dist'
@ -252,4 +254,6 @@ EXTRA_DIST = \
8608_02_mangos_battleground_events.sql \
8618_01_mangos_spell_proc_event.sql \
8676_01_mangos_creature_template.sql \
8688_01_mangos_creature_template.sql \
8693_01_mangos_spell_proc_event.sql \
README

View file

@ -19,6 +19,7 @@
#include "AggressorAI.h"
#include "Errors.h"
#include "Creature.h"
#include "SharedDefines.h"
#include "ObjectAccessor.h"
#include "VMapFactory.h"
#include "World.h"
@ -46,7 +47,7 @@ AggressorAI::MoveInLineOfSight(Unit *u)
if( !m_creature->canFly() && m_creature->GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE )
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() )*/ ) &&
u->isInAccessablePlaceFor(m_creature))
{

View file

@ -800,6 +800,7 @@ void BattleGroundAV::Reset()
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_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++)
{

View file

@ -1746,11 +1746,12 @@ bool Creature::IsVisibleInGridForPlayer(Player* pl) const
if(pl->isGameMaster())
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
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));
}
@ -1766,8 +1767,8 @@ bool Creature::IsVisibleInGridForPlayer(Player* pl) const
}
}
// Dead player see ghosts
if (GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_GHOST)
// Dead player can see ghosts
if (GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_GHOST_VISIBLE)
return true;
// 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_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_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

View file

@ -247,6 +247,25 @@ enum Difficulty
#define MAX_RAID_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
{
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 "DestinationHolder.h"
#include "Unit.h"
#include <cmath>

View file

@ -522,7 +522,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
// Spawn if necessary (loaded grids only)
Map* map = const_cast<Map*>(MapManager::Instance().CreateBaseMap(data->mapid));
// 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;
//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
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
if(!map->Instanceable() && !map->IsRemovalGrid(data->posX, data->posY))
if(!map->Instanceable() && map->IsLoaded(data->posX, data->posY))
{
GameObject* pGameobject = new GameObject;
//sLog.outDebug("Spawning gameobject %u", *itr);

View file

@ -1596,7 +1596,7 @@ InstanceGroupBind* Group::GetBoundInstance(Player* player)
InstanceGroupBind* Group::GetBoundInstance(Map* aMap)
{
// Currently spawn numbering not different from map difficulty
Difficulty difficulty = Difficulty(aMap->GetSpawnMode());
Difficulty difficulty = GetDifficulty(aMap->IsRaid());
// some instances only have one 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)
{
if (Player* pl = GetOwner())

View file

@ -313,6 +313,8 @@ class MANGOS_DLL_SPEC Item : public Object
bool IsPotion() const { return GetProto()->IsPotion(); }
bool IsConjuredConsumable() const { return GetProto()->IsConjuredConsumable(); }
void AddToClientUpdateList();
void RemoveFromClientUpdateList();
void BuildUpdateData(UpdateDataMapType& update_players);
private:
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 !
// 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())
@ -3415,3 +3418,25 @@ DynamicObject* Map::GetDynamicObject(uint64 guid)
{
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 );
}
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(); }
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);
@ -428,6 +434,16 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
DynamicObject* GetDynamicObject(uint64 guid);
TypeUnorderedMapContainer<AllMapStoredObjectTypes>& GetObjectsStore() { return m_objectsStore; }
void AddUpdateObject(Object *obj)
{
i_objectsToClientUpdate.insert(obj);
}
void RemoveUpdateObject(Object *obj)
{
i_objectsToClientUpdate.erase( obj );
}
private:
void LoadMapAndVMap(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 ScriptsProcess();
void SendObjectUpdates();
std::set<Object *> i_objectsToClientUpdate;
protected:
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
// the instance will be created for the first time
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 "Database/DatabaseEnv.h"
#include "Log.h"
#include "ObjectAccessor.h"
#include "Transports.h"
#include "GridDefines.h"
#include "MapInstanced.h"
@ -268,7 +267,6 @@ MapManager::Update(uint32 diff)
iter->second->Update(i_timer.GetCurrent());
}
ObjectAccessor::Instance().Update(i_timer.GetCurrent());
for (TransportSet::iterator iter = m_Transports.begin(); iter != m_Transports.end(); ++iter)
(*iter)->Update(i_timer.GetCurrent());

View file

@ -31,7 +31,6 @@
#include "UpdateMask.h"
#include "Util.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Log.h"
#include "Transports.h"
#include "TargetedMovementGenerator.h"
@ -80,9 +79,6 @@ Object::Object( ) : m_PackGUID(sizeof(uint64)+1)
Object::~Object( )
{
if(m_objectUpdated)
ObjectAccessor::Instance().RemoveUpdateObject(this);
if(m_uint32Values)
{
if(IsInWorld())
@ -744,10 +740,11 @@ void Object::ClearUpdateMask(bool remove)
if(m_uint32Values_mirror[index]!= m_uint32Values[index])
m_uint32Values_mirror[index] = m_uint32Values[index];
}
if(m_objectUpdated)
{
if(remove)
ObjectAccessor::Instance().RemoveUpdateObject(this);
RemoveFromClientUpdateList();
m_objectUpdated = false;
}
}
@ -801,7 +798,7 @@ void Object::SetInt32Value( uint16 index, int32 value )
{
if(!m_objectUpdated)
{
ObjectAccessor::Instance().AddUpdateObject(this);
AddToClientUpdateList();
m_objectUpdated = true;
}
}
@ -820,7 +817,7 @@ void Object::SetUInt32Value( uint16 index, uint32 value )
{
if(!m_objectUpdated)
{
ObjectAccessor::Instance().AddUpdateObject(this);
AddToClientUpdateList();
m_objectUpdated = true;
}
}
@ -839,7 +836,7 @@ void Object::SetUInt64Value( uint16 index, const uint64 &value )
{
if(!m_objectUpdated)
{
ObjectAccessor::Instance().AddUpdateObject(this);
AddToClientUpdateList();
m_objectUpdated = true;
}
}
@ -858,7 +855,7 @@ void Object::SetFloatValue( uint16 index, float value )
{
if(!m_objectUpdated)
{
ObjectAccessor::Instance().AddUpdateObject(this);
AddToClientUpdateList();
m_objectUpdated = true;
}
}
@ -884,7 +881,7 @@ void Object::SetByteValue( uint16 index, uint8 offset, uint8 value )
{
if(!m_objectUpdated)
{
ObjectAccessor::Instance().AddUpdateObject(this);
AddToClientUpdateList();
m_objectUpdated = true;
}
}
@ -910,7 +907,7 @@ void Object::SetUInt16Value( uint16 index, uint8 offset, uint16 value )
{
if(!m_objectUpdated)
{
ObjectAccessor::Instance().AddUpdateObject(this);
AddToClientUpdateList();
m_objectUpdated = true;
}
}
@ -979,7 +976,7 @@ void Object::SetFlag( uint16 index, uint32 newFlag )
{
if(!m_objectUpdated)
{
ObjectAccessor::Instance().AddUpdateObject(this);
AddToClientUpdateList();
m_objectUpdated = true;
}
}
@ -1000,7 +997,7 @@ void Object::RemoveFlag( uint16 index, uint32 oldFlag )
{
if(!m_objectUpdated)
{
ObjectAccessor::Instance().AddUpdateObject(this);
AddToClientUpdateList();
m_objectUpdated = true;
}
}
@ -1025,7 +1022,7 @@ void Object::SetByteFlag( uint16 index, uint8 offset, uint8 newFlag )
{
if(!m_objectUpdated)
{
ObjectAccessor::Instance().AddUpdateObject(this);
AddToClientUpdateList();
m_objectUpdated = true;
}
}
@ -1050,7 +1047,7 @@ void Object::RemoveByteFlag( uint16 index, uint8 offset, uint8 oldFlag )
{
if(!m_objectUpdated)
{
ObjectAccessor::Instance().AddUpdateObject(this);
AddToClientUpdateList();
m_objectUpdated = true;
}
}
@ -1079,6 +1076,24 @@ void Object::BuildUpdateDataForPlayer(Player* pl, UpdateDataMapType& update_play
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()
: 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)
@ -1871,6 +1886,16 @@ void WorldObject::UpdateObjectVisibility()
GetMap()->UpdateObjectVisibility(this, cell, p);
}
void WorldObject::AddToClientUpdateList()
{
GetMap()->AddUpdateObject(this);
}
void WorldObject::RemoveFromClientUpdateList()
{
GetMap()->RemoveUpdateObject(this);
}
struct WorldObjectChangeAccumulator
{
UpdateDataMapType &i_updateDatas;

View file

@ -124,7 +124,7 @@ class MANGOS_DLL_SPEC Object
m_inWorld = true;
// 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()
{
@ -148,7 +148,11 @@ class MANGOS_DLL_SPEC Object
virtual void BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) const;
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 BuildOutOfRangeUpdateBlock( UpdateData *data ) 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 _SetCreateBits(UpdateMask *updateMask, Player *target) const;
void BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2 ) const;
void BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, UpdateMask *updateMask, Player *target ) const;
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...
Map const* GetBaseMap() const;
void AddToClientUpdateList();
void RemoveFromClientUpdateList();
void BuildUpdateData(UpdateDataMapType &);
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;
}
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
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)
{
HashMapHolder<Player>::Remove(pl);
Guard guard(i_updateGuard);
i_objects.erase((Object *)pl);
}
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);
void RemoveCorpse(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 MaNGOS::GeneralLock<LockType > Guard;
std::set<Object *> i_objects;
LockType i_playerGuard;
LockType i_updateGuard;
LockType i_corpseGuard;
};

View file

@ -1041,6 +1041,14 @@ void ObjectMgr::LoadCreatures()
if(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());
do
@ -1080,6 +1088,16 @@ void ObjectMgr::LoadCreatures()
int16 gameEvent = fields[18].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())
{
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)
{
MapEntry const* map = sMapStore.LookupEntry(data.mapid);
if(!map || !map->IsDungeon())
if(!mapEntry || !mapEntry->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);
}
@ -1209,6 +1226,14 @@ void ObjectMgr::LoadGameobjects()
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());
do
@ -1259,6 +1284,16 @@ void ObjectMgr::LoadGameobjects()
data.rotation3 = fields[10].GetFloat();
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())
{
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
if (remaintime != -1 && !IsPositiveEffect(spellid, effindex))
{
if(remaintime <= int32(timediff))
if (remaintime/IN_MILISECONDS <= int32(timediff))
continue;
remaintime -= timediff;
remaintime -= timediff*IN_MILISECONDS;
}
// prevent wrong values of remaincharges

View file

@ -2072,24 +2072,10 @@ void Player::RegenerateHealth(uint32 diff)
ModifyHealth(int32(addvalue));
}
bool Player::CanInteractWithNPCs(bool alive) const
{
if(alive && !isAlive())
return false;
if(isInFlight())
return false;
return true;
}
Creature*
Player::GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask)
Creature* Player::GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask)
{
// unit checks
if (!guid)
return NULL;
if(!IsInWorld())
if (!guid || !IsInWorld() || isInFlight())
return NULL;
// exist (we need look pets also for some interaction (quest/etc)
@ -2097,15 +2083,15 @@ Player::GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask)
if (!unit)
return NULL;
// player check
if(!CanInteractWithNPCs(!(unit->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_GHOST)))
return NULL;
// appropriate npc type
if (npcflagmask && !unit->HasFlag( UNIT_NPC_FLAGS, npcflagmask ))
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;
// not allow interaction under control, but allow with own pets
@ -14835,10 +14821,10 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff)
// negative effects should continue counting down after logout
if (remaintime != -1 && !IsPositiveEffect(spellid, effindex))
{
if(remaintime <= int32(timediff))
if (remaintime/IN_MILISECONDS <= int32(timediff))
continue;
remaintime -= timediff;
remaintime -= timediff*IN_MILISECONDS;
}
// 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);
Creature* GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask);
bool CanInteractWithNPCs(bool alive = true) const;
GameObject* GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes type) const;
void UpdateVisibilityForPlayer();

View file

@ -243,7 +243,7 @@ bool PoolGroup<Creature>::Spawn1Object(uint32 guid)
// Spawn if necessary (loaded grids only)
Map* map = const_cast<Map*>(MapManager::Instance().CreateBaseMap(data->mapid));
// 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;
//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
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
if (!map->Instanceable() && !map->IsRemovalGrid(data->posX, data->posY))
if (!map->Instanceable() && map->IsLoaded(data->posX, data->posY))
{
GameObject* pGameobject = new GameObject;
//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_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_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
QUEST_MANGOS_FLAGS_REPEATABLE = 0x010000, // Set by 1 in SpecialFlags from DB

View file

@ -1883,26 +1883,30 @@ enum CreatureFamily
enum CreatureTypeFlags
{
CREATURE_TYPEFLAGS_TAMEABLE = 0x00001, //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_UNK3 = 0x00004,
CREATURE_TYPEFLAGS_UNK4 = 0x00008,
CREATURE_TYPEFLAGS_UNK5 = 0x00010,
CREATURE_TYPEFLAGS_UNK6 = 0x00020,
CREATURE_TYPEFLAGS_UNK7 = 0x00040,
CREATURE_TYPEFLAGS_UNK8 = 0x00080,
CREATURE_TYPEFLAGS_HERBLOOT = 0x00100, //can be looted by herbalist
CREATURE_TYPEFLAGS_MININGLOOT = 0x00200, //can be looted by miner
CREATURE_TYPEFLAGS_UNK11 = 0x00400,
CREATURE_TYPEFLAGS_UNK12 = 0x00800, //? 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_UNK14 = 0x02000,
CREATURE_TYPEFLAGS_UNK15 = 0x04000, //? Possibly not in use
CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x08000, //can be looted by engineer
CREATURE_TYPEFLAGS_EXOTIC = 0x10000, //can be tamed by hunter as exotic pet
CREATURE_TYPEFLAGS_UNK18 = 0x20000, //? Related to veichles/pvp?
CREATURE_TYPEFLAGS_UNK19 = 0x40000, //? Related to veichle/siege weapons?
CREATURE_TYPEFLAGS_UNK20 = 0x80000
CREATURE_TYPEFLAGS_TAMEABLE = 0x000001, // Tameable by any hunter
CREATURE_TYPEFLAGS_GHOST_VISIBLE = 0x000002, // Creatures which can _also_ be seen when player is a ghost
CREATURE_TYPEFLAGS_UNK3 = 0x000004,
CREATURE_TYPEFLAGS_UNK4 = 0x000008,
CREATURE_TYPEFLAGS_UNK5 = 0x000010,
CREATURE_TYPEFLAGS_UNK6 = 0x000020,
CREATURE_TYPEFLAGS_UNK7 = 0x000040,
CREATURE_TYPEFLAGS_UNK8 = 0x000080,
CREATURE_TYPEFLAGS_HERBLOOT = 0x000100, // Can be looted by herbalist
CREATURE_TYPEFLAGS_MININGLOOT = 0x000200, // Can be looted by miner
CREATURE_TYPEFLAGS_UNK11 = 0x000400,
CREATURE_TYPEFLAGS_UNK12 = 0x000800, // ? Related to mounts in some way. If mounted, fight mounted, mount appear as independant when rider dies?
CREATURE_TYPEFLAGS_UNK13 = 0x001000, // ? Can aid any player in combat if in range?
CREATURE_TYPEFLAGS_UNK14 = 0x002000,
CREATURE_TYPEFLAGS_UNK15 = 0x004000, // ? Possibly not in use
CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x008000, // Can be looted by engineer
CREATURE_TYPEFLAGS_EXOTIC = 0x010000, // Can be tamed by hunter as exotic pet
CREATURE_TYPEFLAGS_UNK18 = 0x020000, // ? Related to vehicles/pvp?
CREATURE_TYPEFLAGS_UNK19 = 0x040000, // ? Related to vehicle/siege weapons?
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

View file

@ -3930,7 +3930,7 @@ SpellCastResult Spell::CheckCast(bool strict)
if(m_spellInfo->TargetAuraStateNot && target->HasAuraState(AuraState(m_spellInfo->TargetAuraStateNot)))
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;
// 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->EffectImplicitTargetA[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->RequiresSpellFocus))
m_spellInfo->EffectImplicitTargetA[j] == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT)
{
SpellScriptTargetBounds bounds = spellmgr.GetSpellScriptTargetBounds(m_spellInfo->Id);
@ -4241,6 +4240,11 @@ SpellCastResult Spell::CheckCast(bool strict)
}
//Missing DB Entry or targets for this spellEffect.
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
if(m_triggeredByAuraSpell || m_IsTriggeredSpell)
@ -4251,6 +4255,7 @@ SpellCastResult Spell::CheckCast(bool strict)
}
}
}
}
if(!m_IsTriggeredSpell)
{

View file

@ -1450,10 +1450,10 @@ void Aura::HandleAddTargetTrigger(bool apply, bool /*Real*/)
void Aura::TriggerSpell()
{
Unit* caster = GetCaster();
const uint64& casterGUID = GetCasterGUID();
Unit* target = GetTriggerTarget();
if(!caster || !target)
if(!casterGUID || !target)
return;
// generic casting code with custom spells and target/caster customs
@ -1479,9 +1479,9 @@ void Aura::TriggerSpell()
case 17949:
case 27252:
{
if (caster->GetTypeId()!=TYPEID_PLAYER)
if (target->GetTypeId() != TYPEID_PLAYER)
return;
Item* item = ((Player*)caster)->GetWeaponForAttack(BASE_ATTACK);
Item* item = ((Player*)target)->GetWeaponForAttack(BASE_ATTACK);
if (!item)
return;
uint32 enchant_id = 0;
@ -1496,10 +1496,10 @@ void Aura::TriggerSpell()
return;
}
// 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);
// add new enchanting
((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true);
((Player*)target)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true);
return;
}
// // Periodic Mana Burn
@ -1542,14 +1542,13 @@ void Aura::TriggerSpell()
// Restoration
case 23493:
{
int32 heal = caster->GetMaxHealth() / 10;
caster->DealHeal(caster, heal, auraSpellInfo);
int32 heal = target->GetMaxHealth() / 10;
target->DealHeal(target, heal, auraSpellInfo);
int32 mana = caster->GetMaxPower(POWER_MANA);
if (mana)
if (int32 mana = target->GetMaxPower(POWER_MANA))
{
mana /= 10;
caster->EnergizeBySpell(caster, 23493, mana, POWER_MANA);
target->EnergizeBySpell(target, 23493, mana, POWER_MANA);
}
return;
}
@ -1579,7 +1578,7 @@ void Aura::TriggerSpell()
case 25371:
{
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;
}
// // Pain Spike
@ -1606,7 +1605,7 @@ void Aura::TriggerSpell()
case 27808:
{
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;
}
// // Detonate Mana
@ -1657,6 +1656,9 @@ void Aura::TriggerSpell()
// Extract Gas
case 30427:
{
Unit* caster = GetCaster();
if (!caster)
return;
// move loot to player inventory and despawn target
if(caster->GetTypeId() ==TYPEID_PLAYER &&
target->GetTypeId() == TYPEID_UNIT &&
@ -1700,13 +1702,18 @@ void Aura::TriggerSpell()
case 31373:
{
// 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;
}
// // Bloodmyst Tesla
// case 31611: break;
// // Doomfire
// case 31944: break;
// Doomfire
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
// case 32236: break;
// // Earthquake
@ -1722,9 +1729,9 @@ void Aura::TriggerSpell()
{
// cast 24 spells 34269-34289, 34314-34316
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)
caster->CastSpell(m_target, spell_id, true);
target->CastSpell(target, spell_id, true, NULL, this, casterGUID);
return;
}
// // Gravity Lapse
@ -1815,7 +1822,10 @@ void Aura::TriggerSpell()
if(m_target->GetTypeId() != TYPEID_UNIT)
return;
caster->CastSpell(caster, 38495, true);
if (Unit* caster = GetCaster())
caster->CastSpell(caster, 38495, true, NULL, this);
else
return;
Creature* creatureTarget = (Creature*)m_target;
@ -2073,7 +2083,7 @@ void Aura::TriggerSpell()
bool all = true;
for(int i = 0; i < MAX_TOTEM; ++i)
{
if(!caster->m_TotemSlot[i])
if(!target->m_TotemSlot[i])
{
all = false;
break;
@ -2081,9 +2091,9 @@ void Aura::TriggerSpell()
}
if(all)
caster->CastSpell(caster, 38437, true);
target->CastSpell(target, 38437, true, NULL, this);
else
caster->RemoveAurasDueToSpell(38437);
target->RemoveAurasDueToSpell(38437);
return;
}
default:
@ -2113,14 +2123,14 @@ void Aura::TriggerSpell()
// 2) maybe aura must be replace by new with accumulative stat mods instead stacking
// prevent cast by triggered auras
if(m_caster_guid == m_target->GetGUID())
if(casterGUID == target->GetGUID())
return;
// stop triggering after each affected stats lost > 90
int32 intelectLoss = 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)
{
if ((*i)->GetId() == 1010)
@ -2137,47 +2147,52 @@ void Aura::TriggerSpell()
if(intelectLoss <= -90 && spiritLoss <= -90)
return;
caster = target;
break;
}
// Mana Tide
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;
}
// Ground Slam
case 33525:
target->CastSpell(target, trigger_spell_id, true);
target->CastSpell(target, trigger_spell_id, true, NULL, this, casterGUID);
return;
// Beacon of Light
case 53563:
// 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;
}
}
// All ok cast by default case
if(triggeredSpellInfo)
caster->CastSpell(target, triggeredSpellInfo, true, 0, this);
else if(target->GetTypeId()!=TYPEID_UNIT || !Script->EffectDummyCreature(caster, GetId(), GetEffIndex(), (Creature*)target))
target->CastSpell(target, triggeredSpellInfo, true, NULL, this, casterGUID);
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());
}
}
}
void Aura::TriggerSpellWithValue()
{
Unit* caster = GetCaster();
const uint64& casterGUID = GetCasterGUID();
Unit* target = GetTriggerTarget();
if(!caster || !target)
if(!casterGUID || !target)
return;
// generic casting code with custom spells and target/caster customs
uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
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);
}
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;
}
@ -6245,9 +6270,6 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real)
void Aura::PeriodicTick()
{
if (!m_target->isAlive() != IsDeathOnlySpell(GetSpellProto()))
return;
switch(m_modifier.m_auraname)
{
case SPELL_AURA_PERIODIC_DAMAGE:

View file

@ -2205,31 +2205,6 @@ void SpellMgr::LoadSpellScriptTarget()
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
switch (type)
{

View file

@ -104,6 +104,7 @@ Unit::Unit()
//m_AurasCheck = 2000;
//m_removeAuraTimer = 4;
m_AurasUpdateIterator = m_Auras.end();
m_AuraFlags = 0;
m_Visibility = VISIBILITY_ON;
@ -5386,6 +5387,12 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 63106;
break;
}
// Glyph of Life Tap
case 63320:
{
triggered_spell_id = 63321;
break;
}
}
break;
}
@ -6276,8 +6283,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
case 10605: spellId = 45300; break; // Rank 4
case 25439: spellId = 45301; break; // Rank 5
case 25442: spellId = 45302; break; // Rank 6
case 49268: spellId = 49270; break; // Rank 7
case 49269: spellId = 49271; break; // Rank 8
case 49270: spellId = 49268; break; // Rank 7
case 49271: spellId = 49269; break; // Rank 8
default:
sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (LO)", procSpell->Id);
return false;
@ -9603,11 +9610,10 @@ bool Unit::isTargetableForAttack(bool inverseAlive /*=false*/) const
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE))
return false;
// target is dead or has ghost-flag
if ((!isAlive() || (GetTypeId() == TYPEID_UNIT && ((Creature *)this)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_GHOST)) != inverseAlive)
if ((isAlive() && !isInvisibleForAlive()) == inverseAlive)
return false;
return IsInWorld() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/;
return IsInWorld() && !hasUnitState(UNIT_STAT_DIED) && !isInFlight();
}
int32 Unit::ModifyHealth(int32 dVal)
@ -9766,6 +9772,10 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
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
if (m_Visibility == VISIBILITY_ON && u->m_invisibilityMask==0 && InSamePhase(u))
return true;
@ -10622,6 +10632,15 @@ bool Unit::isVisibleForInState( Player const* u, WorldObject const* viewPoint, b
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
{
if(GetTypeId() == TYPEID_PLAYER)

View file

@ -469,6 +469,12 @@ enum DamageEffectType
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
{
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;
// function for low level grid visibility checks in player/creature cases
virtual bool IsVisibleInGridForPlayer(Player* pl) const = 0;
bool isInvisibleForAlive() const;
AuraList & GetSingleCastAuras() { 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;
uint32 m_AuraFlags;
uint32 GetDisplayId() { return GetUInt32Value(UNIT_FIELD_DISPLAYID); }
void SetDisplayId(uint32 modelId);
uint32 GetNativeDisplayId() { return GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID); }

View file

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

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__
#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"
#endif // __REVISION_SQL_H__