mirror of
https://github.com/mangosfour/server.git
synced 2025-12-16 04:37:00 +00:00
Merge commit 'origin/master' into 330
This commit is contained in:
commit
5e15a6553c
36 changed files with 351 additions and 213 deletions
|
|
@ -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 */;
|
||||
|
|
|
|||
5
sql/updates/8688_01_mangos_creature_template.sql
Normal file
5
sql/updates/8688_01_mangos_creature_template.sql
Normal 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);
|
||||
4
sql/updates/8693_01_mangos_spell_proc_event.sql
Normal file
4
sql/updates/8693_01_mangos_spell_proc_event.sql
Normal 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);
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "MapManager.h"
|
||||
#include "DestinationHolder.h"
|
||||
#include "Unit.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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); }
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "8677"
|
||||
#define REVISION_NR "8700"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
|
|
@ -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__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue