Transports - phase 3

- The gnome engineers have finally repaired the computers of DeeprunTram, and now both trams travel properly between stations.
  - The pets try hard to learn the paths. For example, they will now properly follow their masters on bridges.
  - There are now 2 types of transporters: local transporters (elevators, platforms) and global transporters (ships, zeppelins).
  - Some obsolete methods have been removed.
  - Some methods have been rewritten to make room for the final phase.
This commit is contained in:
H0zen 2016-12-27 16:11:26 +02:00
parent d9fa1c272f
commit 59156f5ec1
28 changed files with 522 additions and 610 deletions

View File

@ -1,59 +0,0 @@
# MaNGOS is a full featured server for World of Warcraft, supporting
# the following clients: 1.12.x, 2.4.3, 3.2.5a, 4.2.3 and 5.4.8
#
# Copyright (C) 2005-2016 MaNGOS project <https://getmangos.eu>
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ***** END GPL LICENSE BLOCK *****
#
# World of Warcraft, and all World of Warcraft or Warcraft art, images,
# and lore are copyrighted by Blizzard Entertainment, Inc.
include(MacroMangosSourceGroup)
#-----------------------------------------------------------------------------
# Define the battleground library
file(GLOB sources *.cpp)
file(GLOB headers *.h)
set(battleground_LIB_SRCS ${sources} ${headers})
mangos_source_group(${battleground_LIB_SRCS})
include_directories(
${ACE_INCLUDE_DIRS}
${MYSQL_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/dep/include/g3dlite/
${CMAKE_SOURCE_DIR}/src/framework/
${CMAKE_SOURCE_DIR}/src/shared/
${CMAKE_SOURCE_DIR}/src/game/
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}/src/shared/
)
#-----------------------------------------------------------------------------
# Build the battleground library
add_library(mangos-battleground STATIC ${battleground_LIB_SRCS})
target_link_libraries(mangos-battleground mangos-shared mangos-framework g3dlite ${ACE_LIBRARIES} ${MYSQL_LIBRARIES})
if(${CMAKE_BUILD_TYPE} MATCHES Debug)
set(BUILD_PROPERTIES "-DMANGOS_DEBUG")
set_target_properties(mangos-battleground PROPERTIES COMPILE_FLAGS ${BUILD_PROPERTIES})
endif()

View File

@ -137,18 +137,11 @@ void Camera::UpdateVisibilityOf(WorldObject* target)
m_owner.UpdateVisibilityOf(m_source, target);
}
template<class T>
void Camera::UpdateVisibilityOf(T* target, UpdateData& data, std::set<WorldObject*>& vis)
void Camera::UpdateVisibilityOf(WorldObject* target, UpdateData& data, std::set<WorldObject*>& vis)
{
m_owner.template UpdateVisibilityOf<T>(m_source, target, data, vis);
m_owner.UpdateVisibilityOf(m_source, target, data, vis);
}
template void Camera::UpdateVisibilityOf(Player* , UpdateData& , std::set<WorldObject*>&);
template void Camera::UpdateVisibilityOf(Creature* , UpdateData& , std::set<WorldObject*>&);
template void Camera::UpdateVisibilityOf(Corpse* , UpdateData& , std::set<WorldObject*>&);
template void Camera::UpdateVisibilityOf(GameObject* , UpdateData& , std::set<WorldObject*>&);
template void Camera::UpdateVisibilityOf(DynamicObject* , UpdateData& , std::set<WorldObject*>&);
void Camera::UpdateVisibilityForOwner()
{
MaNGOS::VisibleNotifier notifier(*this);

View File

@ -54,8 +54,7 @@ class Camera
// set view to camera's owner
void ResetView(bool update_far_sight_field = true);
template<class T>
void UpdateVisibilityOf(T* obj, UpdateData& d, std::set<WorldObject*>& vis);
void UpdateVisibilityOf(WorldObject* obj, UpdateData& d, std::set<WorldObject*>& vis);
void UpdateVisibilityOf(WorldObject* obj);
void ReceivePacket(WorldPacket* data);

View File

@ -158,6 +158,12 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, float x, float
return false;
}
if (goinfo->type >= MAX_GAMEOBJECT_TYPE)
{
sLog.outErrorDb("Gameobject (GUID: %u) not created: Entry %u has invalid type %u in `gameobject_template`. It may crash client if created.", guidlow, name_id, goinfo->type);
return false;
}
Object::_Create(guidlow, goinfo->id, HIGHGUID_GAMEOBJECT);
// let's make sure we don't send the client invalid quaternion
@ -181,32 +187,17 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, float x, float
}
SetQuaternion(q);
m_goInfo = goinfo;
if (goinfo->type >= MAX_GAMEOBJECT_TYPE)
{
sLog.outErrorDb("Gameobject (GUID: %u) not created: Entry %u has invalid type %u in `gameobject_template`. It may crash client if created.", guidlow, name_id, goinfo->type);
return false;
}
SetObjectScale(goinfo->size);
SetGOInfo(goinfo);
SetObjectScale(m_goInfo->size);
SetFloatValue(GAMEOBJECT_POS_X, x);
SetFloatValue(GAMEOBJECT_POS_Y, y);
SetFloatValue(GAMEOBJECT_POS_Z, z);
SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction);
SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT)
{ SetFlag(GAMEOBJECT_FLAGS, (GO_FLAG_TRANSPORT | GO_FLAG_NODESPAWN)); }
SetEntry(goinfo->id);
SetDisplayId(goinfo->displayId);
SetUInt32Value(GAMEOBJECT_FACTION, m_goInfo->faction);
SetUInt32Value(GAMEOBJECT_FLAGS, m_goInfo->flags);
SetEntry(m_goInfo->id);
SetDisplayId(m_goInfo->displayId);
SetGoState(go_state);
SetGoType(GameobjectTypes(goinfo->type));
SetGoType(GameobjectTypes(m_goInfo->type));
SetGoAnimProgress(animprogress);
@ -752,11 +743,6 @@ void GameObject::DeleteFromDB()
WorldDatabase.PExecuteLog("DELETE FROM gameobject_battleground WHERE guid = '%u'", GetGUIDLow());
}
GameObjectInfo const* GameObject::GetGOInfo() const
{
return m_goInfo;
}
/*********************************************************/
/*** QUEST SYSTEM ***/
/*********************************************************/
@ -1801,7 +1787,7 @@ void GameObject::RollIfMineralVein()
GameObjectInfo const* goinfo = ObjectMgr::GetGameObjectInfo(GetEntry());
if (goinfo->chest.minSuccessOpens != 0 && goinfo->chest.maxSuccessOpens > goinfo->chest.minSuccessOpens) //in this case it is a mineral vein
{
uint32 entrynew = RollMineralVein(GetRealEntry());
uint32 entrynew = RollMineralVein(GetObjectGuid().GetEntry());
GameObjectInfo const* goinfonew = ObjectMgr::GetGameObjectInfo(entrynew);
m_goInfo = goinfonew;

View File

@ -565,7 +565,9 @@ class GameObject : public WorldObject
bool Create(uint32 guidlow, uint32 name_id, Map* map, float x, float y, float z, float ang,
float rotation0 = 0.0f, float rotation1 = 0.0f, float rotation2 = 0.0f, float rotation3 = 0.0f, uint32 animprogress = GO_ANIMPROGRESS_DEFAULT, GOState go_state = GO_STATE_READY);
void Update(uint32 update_diff, uint32 p_time) override;
GameObjectInfo const* GetGOInfo() const;
GameObjectInfo const* GetGOInfo() const { return m_goInfo; }
void SetGOInfo(GameObjectInfo const* pg) { m_goInfo = pg; }
bool IsTransport() const;
@ -584,7 +586,7 @@ class GameObject : public WorldObject
void SaveToDB();
void SaveToDB(uint32 mapid);
bool LoadFromDB(uint32 guid, Map* map);
void DeleteFromDB();
virtual void DeleteFromDB();
void SetOwnerGuid(ObjectGuid ownerGuid)
{

View File

@ -1226,7 +1226,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float& z, Map* atMap
// non swim unit must be at ground (mostly speedup, because it don't must be in water and water level check less fast
if (!((Creature const*)this)->CanFly())
{
bool canSwim = ((Creature const*)this)->CanSwim();
bool canSwim = ((Creature const*)this)->CanSwim() && ((Creature const*)this)->IsInWater();
float ground_z = z;
float max_z = canSwim
? atMap->GetTerrain()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK))

View File

@ -149,11 +149,9 @@ class Object
}
ObjectGuid const& GetObjectGuid() const { return GetGuidValue(OBJECT_FIELD_GUID); }
const uint64& GetGUID() const { return GetUInt64Value(OBJECT_FIELD_GUID); } // DEPRECATED, not use, will removed soon
uint32 GetGUIDLow() const { return GetObjectGuid().GetCounter(); }
PackedGuid const& GetPackGUID() const { return m_PackGUID; }
std::string GetGuidStr() const { return GetObjectGuid().GetString(); }
uint32 GetRealEntry() const { return GetObjectGuid().GetEntry(); } //returns the db entry needed for mineral spawn system
uint32 GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY); }
void SetEntry(uint32 entry) { SetUInt32Value(OBJECT_FIELD_ENTRY, entry); }

View File

@ -759,7 +759,7 @@ void ObjectMgr::LoadCreatureItemTemplates()
if (!eqInfo)
{ continue; }
EquipmentInfoItem const* itemProto = GetEquipmentInfoItem(eqInfo->entry);
switch (itemProto->InventoryType)
@ -1199,12 +1199,10 @@ void ObjectMgr::LoadCreatures()
}
if (gameEvent == 0 && GuidPoolId == 0 && EntryPoolId == 0) // if not this is to be managed by GameEvent System or Pool system
{
AddCreatureToGrid(guid, &data);
{ AddCreatureToGrid(guid, &data); }
if (cInfo->ExtraFlags & CREATURE_EXTRA_FLAG_ACTIVE)
m_activeCreatures.insert(ActiveCreatureGuidsOnMap::value_type(data.mapid, guid));
}
if (cInfo->ExtraFlags & CREATURE_EXTRA_FLAG_ACTIVE)
{ m_activeCreatures.insert(ActiveCreatureGuidsOnMap::value_type(data.mapid, guid)); }
++count;
}
@ -1236,14 +1234,12 @@ void ObjectMgr::RemoveCreatureFromGrid(uint32 guid, CreatureData const* data)
void ObjectMgr::LoadGameObjects()
{
uint32 count = 0;
// 0 1 2 3 4 5 6
QueryResult* result = WorldDatabase.Query("SELECT gameobject.guid, gameobject.id, map, position_x, position_y, position_z, orientation,"
// 7 8 9 10 11 12 13 14
"rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, event,"
// 15 16
"pool_gameobject.pool_entry, pool_gameobject_template.pool_entry "
// 0 1 2 3 4 5 6
QueryResult* result = WorldDatabase.Query("SELECT gameobject.guid, gameobject.id, gameobject.map, gameobject.position_x, gameobject.position_y, gameobject.position_z, gameobject.orientation, "
// 7 8 9 10 11 12 13
"gameobject.rotation0, gameobject.rotation1, gameobject.rotation2, gameobject.rotation3, gameobject.spawntimesecs, gameobject.animprogress, gameobject.state, "
// 14 15 16
"game_event_gameobject.`event`, pool_gameobject.pool_entry, pool_gameobject_template.pool_entry "
"FROM gameobject "
"LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid "
"LEFT OUTER JOIN pool_gameobject ON gameobject.guid = pool_gameobject.guid "
@ -1260,6 +1256,7 @@ void ObjectMgr::LoadGameObjects()
BarGoLink bar(result->GetRowCount());
uint32 local_transports = 0;
do
{
Field* fields = result->Fetch();
@ -1355,21 +1352,22 @@ void ObjectMgr::LoadGameObjects()
continue;
}
if (gameEvent == 0 && GuidPoolId == 0 && EntryPoolId == 0) // if not this is to be managed by GameEvent System or Pool system
if (gInfo->type != GAMEOBJECT_TYPE_TRANSPORT && gameEvent == 0 && GuidPoolId == 0 && EntryPoolId == 0) // if not this is to be managed by GameEvent System or Pool system
{ AddGameobjectToGrid(guid, &data); }
//uint32 zoneId, areaId;
//sTerrainMgr.LoadTerrain(data.mapid)->GetZoneAndAreaId(zoneId, areaId, data.posX, data.posY, data.posZ);
//sLog.outErrorDb("UPDATE gameobject SET zone_id=%u, area_id=%u WHERE guid=%u;", zoneId, areaId, guid);
++count;
if (gInfo->type == GAMEOBJECT_TYPE_TRANSPORT)
{
m_localTransports.insert(LocalTransportGuidsOnMap::value_type(data.mapid, guid));
++local_transports;
}
}
while (result->NextRow());
delete result;
sLog.outString(">> Loaded " SIZEFMTD " gameobjects", mGameObjectDataMap.size());
sLog.outString();
sLog.outString(">> Loaded " SIZEFMTD " gameobjects", mGameObjectDataMap.size());
sLog.outString(">>> Loaded %u local transport objects", local_transports);
}
void ObjectMgr::AddGameobjectToGrid(uint32 guid, GameObjectData const* data)
@ -8099,56 +8097,6 @@ void ObjectMgr::LoadVendorTemplates()
{ sLog.outErrorDb("Table `npc_vendor_template` has vendor template %u not used by any vendors ", *vItr); }
}
/* This function is supposed to take care of three things:
* 1) Load Transports on Map or on Continents
* 2) Load Active Npcs on Map or Continents
* 3) Load Everything dependend on config setting LoadAllGridsOnMaps
*
* This function is currently WIP, hence parts exist only as draft.
*/
void ObjectMgr::LoadActiveEntities(Map* _map)
{
// Special case on startup - load continents
if (!_map)
{
uint32 continents[] = {0, 1};
for (uint8 i = 0; i < countof(continents); ++i)
{
_map = sMapMgr.FindMap(continents[i]);
if (!_map)
{ _map = sMapMgr.CreateMap(continents[i], NULL); }
if (_map)
{ LoadActiveEntities(_map); }
else
{ sLog.outError("ObjectMgr::LoadActiveEntities - Unable to create Map %u", continents[i]); }
}
return;
}
// Load active objects for _map
if (sWorld.isForceLoadMap(_map->GetId()))
{
for (CreatureDataMap::const_iterator itr = mCreatureDataMap.begin(); itr != mCreatureDataMap.end(); ++itr)
{
if (itr->second.mapid == _map->GetId())
{ _map->ForceLoadGrid(itr->second.posX, itr->second.posY); }
}
}
else // Normal case - Load all npcs that are active
{
std::pair<ActiveCreatureGuidsOnMap::const_iterator, ActiveCreatureGuidsOnMap::const_iterator> bounds = m_activeCreatures.equal_range(_map->GetId());
for (ActiveCreatureGuidsOnMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
{
CreatureData const& data = mCreatureDataMap[itr->second];
{ _map->ForceLoadGrid(data.posX, data.posY); }
}
}
// Load Transports on Map _map
}
void ObjectMgr::LoadNpcGossips()
{

View File

@ -117,6 +117,9 @@ struct MangosStringLocale
typedef UNORDERED_MAP<uint32 /*guid*/, CreatureData> CreatureDataMap;
typedef CreatureDataMap::value_type CreatureDataPair;
typedef std::multimap<uint32 /*mapId*/, uint32 /*guid*/> ActiveCreatureGuidsOnMap;
typedef std::multimap<uint32 /*mapId*/, uint32 /*guid*/> LocalTransportGuidsOnMap;
class FindCreatureData
{
public:
@ -718,9 +721,6 @@ class ObjectMgr
{
LoadTrainers("npc_trainer", false);
}
/// @param _map Map* of the map for which to load active entities. If NULL active entities on continents are loaded
void LoadActiveEntities(Map* _map);
std::string GeneratePetName(uint32 entry);
uint32 GetBaseXP(uint32 level) const;
@ -826,6 +826,8 @@ class ObjectMgr
{ return "There is no info for this item"; }
}
CreatureDataMap const* GetCreatureDataMap() const { return &mCreatureDataMap; }
CreatureDataPair const* GetCreatureDataPair(uint32 guid) const
{
CreatureDataMap::const_iterator itr = mCreatureDataMap.find(guid);
@ -853,6 +855,8 @@ class ObjectMgr
{ break; }
}
ActiveCreatureGuidsOnMap const* GetActiveCreatureGuids() const { return &m_activeCreatures; }
CreatureLocale const* GetCreatureLocale(uint32 entry) const
{
CreatureLocaleMap::const_iterator itr = mCreatureLocaleMap.find(entry);
@ -919,6 +923,7 @@ class ObjectMgr
return &itr->second;
}
LocalTransportGuidsOnMap const* GetLocalTransportGuids() const { return &m_localTransports; }
GameObjectDataPair const* GetGODataPair(uint32 guid) const
{
GameObjectDataMap::const_iterator itr = mGameObjectDataMap.find(guid);
@ -1234,13 +1239,13 @@ class ObjectMgr
HalfNameMap PetHalfName0;
HalfNameMap PetHalfName1;
typedef std::multimap<uint32 /*mapId*/, uint32 /*guid*/> ActiveCreatureGuidsOnMap;
// Array to store creature stats, Max creature level + 1 (for data alignement with in game level)
CreatureClassLvlStats m_creatureClassLvlStats[DEFAULT_MAX_CREATURE_LEVEL + 1][MAX_CREATURE_CLASS];
MapObjectGuids mMapObjectGuids;
ActiveCreatureGuidsOnMap m_activeCreatures;
LocalTransportGuidsOnMap m_localTransports;
CreatureDataMap mCreatureDataMap;
CreatureLocaleMap mCreatureLocaleMap;
GameObjectDataMap mGameObjectDataMap;

View File

@ -14447,10 +14447,10 @@ bool Player::isAllowedToLoot(Creature* creature)
/* This is the player that will be given permission to loot */
Player* final_looter = recipient;
/* Iterate through the valid party members */
Group::MemberSlotList slots = plr_group->GetMemberSlots();
for (Group::MemberSlotList::iterator itr = slots.begin(); itr != slots.end(); ++itr)
{
/* Get the player data */
@ -14473,18 +14473,17 @@ bool Player::isAllowedToLoot(Creature* creature)
/* We have our looter, update their loot time */
final_looter->lastTimeLooted = time(NULL);
/* Update the creature with the looter that has been assigned to them */
creature->assignedLooter = final_looter->GetGUIDLow();
final_looter->GetGroup()->SetLooterGuid(final_looter->GetGUID());
final_looter->GetGroup()->SetLooterGuid(final_looter->GetObjectGuid());
/* Finally, return if we are the assigned looter */
return (final_looter->GetGUIDLow() == GetGUIDLow() || hasSharedLoot || hasStartingQuestLoot);
/* End of switch statement */
}
default:
// Something went wrong, avoid crash
return false;
}
}
@ -16879,7 +16878,7 @@ void Player::HandleStealthedUnitsDetection()
(*i)->SendCreateUpdateToPlayer(this);
m_clientGUIDs.insert(i_guid);
DEBUG_FILTER_LOG(LOG_FILTER_VISIBILITY_CHANGES, "UpdateVisibilityOf(TemplateV): %s is detected in stealth by player %u. Distance = %f", i_guid.GetString().c_str(), GetGUIDLow(), GetDistance(*i));
DEBUG_FILTER_LOG(LOG_FILTER_VISIBILITY_CHANGES, "UpdateVisibilityOf(): %s is detected in stealth by player %u. Distance = %f", i_guid.GetString().c_str(), GetGUIDLow(), GetDistance(*i));
// target aura duration for caster show only if target exist at caster client
// send data at target visibility change (adding to client)
@ -17711,18 +17710,16 @@ bool Player::IsVisibleGloballyFor(Player* u) const
return true;
}
template<class T>
inline void BeforeVisibilityDestroy(T* /*t*/, Player* /*p*/)
inline void BeforeVisibilityDestroy(WorldObject* o, Player* p)
{
if (Creature* t = o->ToCreature())
{
if (p->GetPetGuid() == t->GetObjectGuid() && t->IsPet())
{ ((Pet*)t)->Unsummon(PET_SAVE_REAGENTS); }
}
}
template<>
inline void BeforeVisibilityDestroy<Creature>(Creature* t, Player* p)
{
if (p->GetPetGuid() == t->GetObjectGuid() && ((Creature*)t)->IsPet())
{ ((Pet*)t)->Unsummon(PET_SAVE_REAGENTS); }
}
//2 params version (2p)
void Player::UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* target)
{
if (HaveAtClient(target))
@ -17732,12 +17729,12 @@ void Player::UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* targe
ObjectGuid t_guid = target->GetObjectGuid();
if (target->GetTypeId() == TYPEID_UNIT)
{ BeforeVisibilityDestroy<Creature>((Creature*)target, this); }
{ BeforeVisibilityDestroy(target, this); }
target->DestroyForPlayer(this);
m_clientGUIDs.erase(t_guid);
DEBUG_FILTER_LOG(LOG_FILTER_VISIBILITY_CHANGES, "UpdateVisibilityOf: %s out of range for player %u. Distance = %f", t_guid.GetString().c_str(), GetGUIDLow(), GetDistance(target));
DEBUG_FILTER_LOG(LOG_FILTER_VISIBILITY_CHANGES, "UpdateVisibilityOf(2p): %s out of range for player %u. Distance = %f", t_guid.GetString().c_str(), GetGUIDLow(), GetDistance(target));
}
}
else
@ -17748,7 +17745,7 @@ void Player::UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* targe
if (target->GetTypeId() != TYPEID_GAMEOBJECT || !((GameObject*)target)->IsTransport())
{ m_clientGUIDs.insert(target->GetObjectGuid()); }
DEBUG_FILTER_LOG(LOG_FILTER_VISIBILITY_CHANGES, "UpdateVisibilityOf: %s is visible now for player %u. Distance = %f", target->GetGuidStr().c_str(), GetGUIDLow(), GetDistance(target));
DEBUG_FILTER_LOG(LOG_FILTER_VISIBILITY_CHANGES, "UpdateVisibilityOf(2p): %s is visible now for player %u. Distance = %f", target->GetGuidStr().c_str(), GetGUIDLow(), GetDistance(target));
// target aura duration for caster show only if target exist at caster client
// send data at target visibility change (adding to client)
@ -17758,34 +17755,21 @@ void Player::UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* targe
}
}
template<class T>
inline void UpdateVisibilityOf_helper(GuidSet& s64, T* target)
{
s64.insert(target->GetObjectGuid());
}
template<>
inline void UpdateVisibilityOf_helper(GuidSet& s64, GameObject* target)
{
if (!target->IsTransport())
{ s64.insert(target->GetObjectGuid()); }
}
template<class T>
void Player::UpdateVisibilityOf(WorldObject const* viewPoint, T* target, UpdateData& data, std::set<WorldObject*>& visibleNow)
//4 params version (4p)
void Player::UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* target, UpdateData& data, std::set<WorldObject*>& visibleNow)
{
if (HaveAtClient(target))
{
if (!target->IsVisibleForInState(this, viewPoint, true))
{
BeforeVisibilityDestroy<T>(target, this);
BeforeVisibilityDestroy(target, this);
ObjectGuid t_guid = target->GetObjectGuid();
target->BuildOutOfRangeUpdateBlock(&data);
m_clientGUIDs.erase(t_guid);
DEBUG_FILTER_LOG(LOG_FILTER_VISIBILITY_CHANGES, "UpdateVisibilityOf(TemplateV): %s is out of range for %s. Distance = %f", t_guid.GetString().c_str(), GetGuidStr().c_str(), GetDistance(target));
DEBUG_FILTER_LOG(LOG_FILTER_VISIBILITY_CHANGES, "UpdateVisibilityOf(4p): %s is out of range for %s. Distance = %f", t_guid.GetString().c_str(), GetGuidStr().c_str(), GetDistance(target));
}
}
else
@ -17794,19 +17778,22 @@ void Player::UpdateVisibilityOf(WorldObject const* viewPoint, T* target, UpdateD
{
visibleNow.insert(target);
target->BuildCreateUpdateBlockForPlayer(&data, this);
UpdateVisibilityOf_helper(m_clientGUIDs, target);
DEBUG_FILTER_LOG(LOG_FILTER_VISIBILITY_CHANGES, "UpdateVisibilityOf(TemplateV): %s is visible now for %s. Distance = %f", target->GetGuidStr().c_str(), GetGuidStr().c_str(), GetDistance(target));
if (GameObject* g = target->ToGameObject())
{
if (!g->IsTransport())
{
m_clientGUIDs.insert(g->GetObjectGuid());
}
}
else
{
m_clientGUIDs.insert(target->GetObjectGuid());
}
DEBUG_FILTER_LOG(LOG_FILTER_VISIBILITY_CHANGES, "UpdateVisibilityOf(4p): %s is visible now for %s. Distance = %f", target->GetGuidStr().c_str(), GetGuidStr().c_str(), GetDistance(target));
}
}
}
template void Player::UpdateVisibilityOf(WorldObject const* viewPoint, Player* target, UpdateData& data, std::set<WorldObject*>& visibleNow);
template void Player::UpdateVisibilityOf(WorldObject const* viewPoint, Creature* target, UpdateData& data, std::set<WorldObject*>& visibleNow);
template void Player::UpdateVisibilityOf(WorldObject const* viewPoint, Corpse* target, UpdateData& data, std::set<WorldObject*>& visibleNow);
template void Player::UpdateVisibilityOf(WorldObject const* viewPoint, GameObject* target, UpdateData& data, std::set<WorldObject*>& visibleNow);
template void Player::UpdateVisibilityOf(WorldObject const* viewPoint, DynamicObject* target, UpdateData& data, std::set<WorldObject*>& visibleNow);
void Player::InitPrimaryProfessions()
{
uint32 maxProfs = GetSession()->GetSecurity() < AccountTypes(sWorld.getConfig(CONFIG_UINT32_TRADE_SKILL_GMIGNORE_MAX_PRIMARY_COUNT))

View File

@ -2241,9 +2241,7 @@ class Player : public Unit
bool IsVisibleGloballyFor(Player* pl) const;
void UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* target);
template<class T>
void UpdateVisibilityOf(WorldObject const* viewPoint, T* target, UpdateData& data, std::set<WorldObject*>& visibleNow);
void UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* target, UpdateData& data, std::set<WorldObject*>& visibleNow);
// Stealth detection system
void HandleStealthedUnitsDetection();

View File

@ -1,59 +0,0 @@
# MaNGOS is a full featured server for World of Warcraft, supporting
# the following clients: 1.12.x, 2.4.3, 3.2.5a, 4.2.3 and 5.4.8
#
# Copyright (C) 2005-2016 MaNGOS project <https://getmangos.eu>
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ***** END GPL LICENSE BLOCK *****
#
# World of Warcraft, and all World of Warcraft or Warcraft art, images,
# and lore are copyrighted by Blizzard Entertainment, Inc.
include(MacroMangosSourceGroup)
#-----------------------------------------------------------------------------
# Define the outdoor-pvp library
file(GLOB sources *.cpp)
file(GLOB headers *.h)
set(outdoor-pvp_LIB_SRCS ${sources} ${headers})
mangos_source_group(${outdoor-pvp_LIB_SRCS})
include_directories(
${ACE_INCLUDE_DIRS}
${MYSQL_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/dep/include/g3dlite/
${CMAKE_SOURCE_DIR}/src/framework/
${CMAKE_SOURCE_DIR}/src/shared/
${CMAKE_SOURCE_DIR}/src/game/
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}/src/shared/
)
#-----------------------------------------------------------------------------
# Build the outdoor-pvp library
add_library(mangos-outdoor-pvp STATIC ${outdoor-pvp_LIB_SRCS})
target_link_libraries(mangos-outdoor-pvp mangos-shared mangos-framework g3dlite ${ACE_LIBRARIES} ${MYSQL_LIBRARIES})
if(${CMAKE_BUILD_TYPE} MATCHES Debug)
set(BUILD_PROPERTIES "-DMANGOS_DEBUG")
set_target_properties(mangos-outdoor-pvp PROPERTIES COMPILE_FLAGS ${BUILD_PROPERTIES})
endif()

View File

@ -50,13 +50,14 @@ void VisibleNotifier::Notify()
// but exist one case when this possible and object not out of range: transports
if (Transport* transport = player.GetTransport())
{
for (Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr)
for (UnitSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr)
{
if (i_clientGUIDs.find((*itr)->GetObjectGuid()) != i_clientGUIDs.end())
{
// ignore far sight case
(*itr)->UpdateVisibilityOf(*itr, &player);
player.UpdateVisibilityOf(&player, *itr, i_data, i_visibleNow);
if(Player* p = (*itr)->ToPlayer())
{ p->UpdateVisibilityOf(p, &player); }
player.UpdateVisibilityOf(&player, (WorldObject*)(*itr), i_data, i_visibleNow);
i_clientGUIDs.erase((*itr)->GetObjectGuid());
}
}

View File

@ -543,7 +543,7 @@ void Group::SendUpdateToPlayer(Player* pPlayer)
// guess size
WorldPacket data(SMSG_GROUP_LIST, (1 + 1 + 1 + 4 + GetMembersCount() * 20) + 8 + 1 + 8 + 1);
data << (uint8)m_groupType; // group type
data << (uint8)(subGroup | (IsAssistant(pPlayer->GetGUID()) ? 0x80 : 0)); // own flags (groupid | (assistant?0x80:0))
data << (uint8)(subGroup | (IsAssistant(pPlayer->GetObjectGuid()) ? 0x80 : 0)); // own flags (groupid | (assistant?0x80:0))
data << uint32(GetMembersCount() - 1);
for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
@ -1043,7 +1043,7 @@ void Group::CountTheRoll(Rolls::iterator& rollI)
if (Player* player = sObjectMgr.GetPlayer(maxguid))
{
if (Object* object = player->GetMap()->GetWorldObject(roll->lootedTargetGUID))
if (WorldObject* object = player->GetMap()->GetWorldObject(roll->lootedTargetGUID))
{
SendLootRollWon(maxguid, maxresul, ROLL_NEED, *roll);
won = true;
@ -1060,10 +1060,8 @@ void Group::CountTheRoll(Rolls::iterator& rollI)
Item* newitem = player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId);
player->SendNewItem(newitem, uint32(item->count), false, false, true);
if (object->GetTypeId() == TYPEID_UNIT)
if (Creature* creature = object->ToCreature())
{
/// Warn players about the loot status on the corpse.
Creature * creature = object->ToCreature();
/// If creature has been fully looted, remove flag.
if (creature->loot.isLooted())
{
@ -1108,7 +1106,7 @@ void Group::CountTheRoll(Rolls::iterator& rollI)
if (Player* player = sObjectMgr.GetPlayer(maxguid))
{
if (Object * object = player->GetMap()->GetWorldObject(roll->lootedTargetGUID))
if (WorldObject* object = player->GetMap()->GetWorldObject(roll->lootedTargetGUID))
{
SendLootRollWon(maxguid, maxresul, ROLL_GREED, *roll);
won = true;
@ -1124,10 +1122,8 @@ void Group::CountTheRoll(Rolls::iterator& rollI)
--roll->getLoot()->unlootedCount;
Item* newitem = player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId);
player->SendNewItem(newitem, uint32(item->count), false, false, true);
if (object->GetTypeId() == TYPEID_UNIT)
if (Creature* creature = object->ToCreature())
{
/// Warn players about the loot status on the corpse.
Creature * creature = object->ToCreature();
/// If creature has been fully looted, remove flag.
if (creature->loot.isLooted())
{

View File

@ -64,7 +64,7 @@ void WorldSession::HandleMeetingStoneJoinOpcode(WorldPacket& recv_data)
if (Group* grp = _player->GetGroup())
{
if (!grp->IsLeader(_player->GetGUID()))
if (!grp->IsLeader(_player->GetObjectGuid()))
{
SendMeetingstoneFailed(MEETINGSTONE_FAIL_PARTYLEADER);

View File

@ -348,7 +348,7 @@ void LFGQueue::Update(uint32 diff)
}
WorldPacket data;
BuildMemberAddedPacket(data, member->GetGUID());
BuildMemberAddedPacket(data, member->GetObjectGuid());
leader->GetSession()->SendPacket(&data);
@ -432,7 +432,7 @@ bool LFGQueue::FindRoleToGroup(Player* plr, Group* grp, ClassRoles role)
}
WorldPacket data;
BuildMemberAddedPacket(data, plr->GetGUID());
BuildMemberAddedPacket(data, plr->GetObjectGuid());
grp->BroadcastPacket(&data, true);
// Add member to the group.
@ -506,7 +506,7 @@ bool LFGQueue::FindRoleToGroup(Player* plr, Group* grp, ClassRoles role)
}
WorldPacket data;
BuildMemberAddedPacket(data, plr->GetGUID());
BuildMemberAddedPacket(data, plr->GetObjectGuid());
grp->BroadcastPacket(&data, true);
// Add member to the group.

View File

@ -44,6 +44,8 @@
#include "BattleGround/BattleGroundMgr.h"
#include "Chat.h"
#include "Weather.h"
#include "Transports.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#endif /* ENABLE_ELUNA */
@ -70,6 +72,12 @@ Map::~Map()
delete i_data;
i_data = NULL;
// unload all local transporters
for (std::set<Transport*>::iterator t = i_transports.begin(); t != i_transports.end(); ++t)
{
delete *t;
}
// unload instance specific navigation data
MMAP::MMapFactory::createOrGetMMapManager()->unloadMapInstance(m_TerrainData->GetMapId(), GetInstanceId());
@ -121,6 +129,7 @@ Map::Map(uint32 id, time_t expiry, uint32 InstanceId)
m_persistentState->SetUsedByMapState(this);
m_weatherSystem = new WeatherSystem(this);
i_transports.clear();
#ifdef ENABLE_ELUNA
sEluna->OnCreate(this);
#endif /* ENABLE_ELUNA */
@ -527,6 +536,13 @@ void Map::Update(const uint32& t_diff)
}
}
/// update local transports
for (std::set<Transport*>::iterator t = i_transports.begin(); t != i_transports.end(); ++t)
{
WorldObject::UpdateHelper helper(*t);
helper.Update(t_diff);
}
/// update active cells around players and active objects
resetMarkedCells();
@ -946,7 +962,7 @@ void Map::SendInitSelf(Player* player)
// build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map
if (Transport* transport = player->GetTransport())
{
for (Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr)
for (UnitSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr)
{
if (player != (*itr) && player->HaveAtClient(*itr))
{
@ -963,55 +979,87 @@ void Map::SendInitSelf(Player* player)
void Map::SendInitTransports(Player* player)
{
// Hack to send out transports
// Send out global transports
MapManager::TransportMap& tmap = sMapMgr.m_TransportsByMap;
// no transports at map
if (tmap.find(player->GetMapId()) == tmap.end())
{ return; }
UpdateData transData;
MapManager::TransportSet& tset = tmap[player->GetMapId()];
bool hasTransport = false;
for (MapManager::TransportSet::const_iterator i = tset.begin(); i != tset.end(); ++i)
if (tmap.find(player->GetMapId()) != tmap.end())
{
// send data for current transport in other place
if ((*i) != player->GetTransport() && (*i)->GetMapId() == i_id)
MapManager::TransportSet& tset = tmap[player->GetMapId()];
UpdateData transData;
bool hasTransport = false;
for (MapManager::TransportSet::const_iterator i = tset.begin(); i != tset.end(); ++i)
{
hasTransport = true;
(*i)->BuildCreateUpdateBlockForPlayer(&transData, player);
// send data for current transport in other place
if ((*i) != player->GetTransport() && (*i)->GetMapId() == i_id)
{
hasTransport = true;
(*i)->BuildCreateUpdateBlockForPlayer(&transData, player);
}
}
WorldPacket packet;
transData.BuildPacket(&packet, hasTransport);
player->GetSession()->SendPacket(&packet);
}
WorldPacket packet;
transData.BuildPacket(&packet, hasTransport);
player->GetSession()->SendPacket(&packet);
// Now send out local transports
if (i_transports.size() != 0)
{
UpdateData transData;
bool hasTransport = false;
for (MapManager::TransportSet::const_iterator i = i_transports.begin(); i != i_transports.end(); ++i)
{
// send data for current transport in other place
if ((*i) != player->GetTransport() && (*i)->GetMapId() == i_id)
{
hasTransport = true;
(*i)->BuildCreateUpdateBlockForPlayer(&transData, player);
}
}
WorldPacket packet;
transData.BuildPacket(&packet, hasTransport);
player->GetSession()->SendPacket(&packet);
}
}
void Map::SendRemoveTransports(Player* player)
{
// Hack to send out transports
// Global transports
MapManager::TransportMap& tmap = sMapMgr.m_TransportsByMap;
// no transports at map
if (tmap.find(player->GetMapId()) == tmap.end())
{ return; }
if (tmap.find(player->GetMapId()) != tmap.end())
{
UpdateData transData;
MapManager::TransportSet& tset = tmap[player->GetMapId()];
UpdateData transData;
// except used transport
for (MapManager::TransportSet::const_iterator i = tset.begin(); i != tset.end(); ++i)
if ((*i) != player->GetTransport() && (*i)->GetMapId() != i_id)
{ (*i)->BuildOutOfRangeUpdateBlock(&transData); }
MapManager::TransportSet& tset = tmap[player->GetMapId()];
WorldPacket packet;
transData.BuildPacket(&packet);
player->GetSession()->SendPacket(&packet);
}
// except used transport
for (MapManager::TransportSet::const_iterator i = tset.begin(); i != tset.end(); ++i)
if ((*i) != player->GetTransport() && (*i)->GetMapId() != i_id)
{ (*i)->BuildOutOfRangeUpdateBlock(&transData); }
// Local transports
if (i_transports.size() != 0)
{
UpdateData transData;
WorldPacket packet;
transData.BuildPacket(&packet);
player->GetSession()->SendPacket(&packet);
// except used transport
for (MapManager::TransportSet::const_iterator i = i_transports.begin(); i != i_transports.end(); ++i)
if ((*i) != player->GetTransport() && (*i)->GetMapId() != i_id)
{ (*i)->BuildOutOfRangeUpdateBlock(&transData); }
WorldPacket packet;
transData.BuildPacket(&packet);
player->GetSession()->SendPacket(&packet);
}
}
inline void Map::setNGrid(NGridType* grid, uint32 x, uint32 y)
@ -2343,4 +2391,4 @@ bool Map::GetReachableRandomPosition(Unit* unit, float& x, float& y, float& z, f
}
return false;
}
}

View File

@ -63,6 +63,7 @@ class BattleGround;
class GridMap;
class GameObjectModel;
class WeatherSystem;
class Transport;
namespace MaNGOS { struct ObjectUpdater; }
@ -294,6 +295,8 @@ class Map : public GridRefManager<NGridType>
bool GetRandomPointInTheAir(float& x, float& y, float& z, float radius);
bool GetRandomPointUnderWater(float& x, float& y, float& z, float radius, GridMapLiquidData& liquid_status);
void LoadLocalTransports();
private:
void LoadMapAndVMap(int gx, int gy);
@ -358,6 +361,7 @@ class Map : public GridRefManager<NGridType>
std::bitset<TOTAL_NUMBER_OF_CELLS_PER_MAP* TOTAL_NUMBER_OF_CELLS_PER_MAP> marked_cells;
std::set<WorldObject*> i_objectsToRemove;
std::set<Transport*> i_transports;
typedef std::multimap<time_t, ScriptAction> ScriptScheduleMap;
ScriptScheduleMap m_scriptSchedule;

View File

@ -115,7 +115,8 @@ Map* MapManager::CreateMap(uint32 id, const WorldObject* obj)
// create DungeonMap object
m = CreateInstance(id, (Player*)obj);
// Load active objects for this map
sObjectMgr.LoadActiveEntities(m);
if (m != NULL)
{ LoadActiveEntities(m); }
}
else
{
@ -127,6 +128,8 @@ Map* MapManager::CreateMap(uint32 id, const WorldObject* obj)
// add map into container
i_maps[MapID(id)] = m;
LoadActiveEntities(m);
// non-instanceable maps always expected have saved state
m->CreateInstanceData(true);
}
@ -390,3 +393,51 @@ BattleGroundMap* MapManager::CreateBattleGroundMap(uint32 id, uint32 InstanceId,
return map;
}
void MapManager::LoadContinents()
{
uint32 continents[] = {0, 1};
Map* _map = NULL;
for (uint8 i = 0; i < countof(continents); ++i)
{
_map = sMapMgr.FindMap(continents[i]);
if (!_map)
{ _map = sMapMgr.CreateMap(continents[i], NULL); }
if (!_map)
{ sLog.outError("MapManager::LoadContinents() - Unable to create map %u", continents[i]); }
}
return;
}
void MapManager::LoadActiveEntities(Map* m)
{
// Create all local transporters for this map
m->LoadLocalTransports();
// Load grids for all objects on this map, if configured so
if (sWorld.isForceLoadMap(m->GetId()))
{
for (CreatureDataMap::const_iterator itr = sObjectMgr.GetCreatureDataMap()->begin(); itr != sObjectMgr.GetCreatureDataMap()->end(); ++itr)
{
if (itr->second.mapid == m->GetId())
{
m->ForceLoadGrid(itr->second.posX, itr->second.posY);
}
}
}
else // Normal case - load only grids for npcs that are active
{
std::pair<ActiveCreatureGuidsOnMap::const_iterator, ActiveCreatureGuidsOnMap::const_iterator> bounds = sObjectMgr.GetActiveCreatureGuids()->equal_range(m->GetId());
for (ActiveCreatureGuidsOnMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
{
CreatureData const* data = sObjectMgr.GetCreatureData(itr->second);
m->ForceLoadGrid(data->posX, data->posY);
}
}
}

View File

@ -65,7 +65,6 @@ class MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::ClassLevelLockab
Map* CreateMap(uint32, const WorldObject* obj);
Map* CreateBgMap(uint32 mapid, BattleGround* bg);
Map* FindMap(uint32 mapid, uint32 instanceId = 0) const;
void UpdateGridState(grid_state_t state, Map& map, NGridType& ngrid, GridInfo& ginfo, const uint32& x, const uint32& y, const uint32& t_diff);
// only const version for outer users
@ -133,6 +132,7 @@ class MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::ClassLevelLockab
void RemoveAllObjectsInRemoveList();
void LoadContinents();
void LoadTransports();
typedef std::set<Transport*> TransportSet;
@ -172,6 +172,7 @@ class MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::ClassLevelLockab
void InitStateMachine();
void DeleteStateMachine();
void LoadActiveEntities(Map* m);
Map* CreateInstance(uint32 id, Player* player);
DungeonMap* CreateDungeonMap(uint32 id, uint32 InstanceId, DungeonPersistentState* save = NULL);

View File

@ -25,6 +25,7 @@
#include "Common.h"
#include "Transports.h"
#include "Map.h"
#include "MapManager.h"
#include "ObjectMgr.h"
#include "ObjectGuid.h"
@ -34,6 +35,34 @@
#include "DBCStores.h"
#include "ProgressBar.h"
#include <G3D/Quat.h>
void Map::LoadLocalTransports()
{
//load local transports for this map
std::pair<LocalTransportGuidsOnMap::const_iterator, LocalTransportGuidsOnMap::const_iterator> bounds = sObjectMgr.GetLocalTransportGuids()->equal_range(GetId());
for (LocalTransportGuidsOnMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
{
LocalTransport* lt = new LocalTransport();
if (lt->Initialize(itr->second, this))
{
i_transports.insert(lt);
}
else
{
delete lt;
}
}
/*
sLog.outString();
for (std::set<Transport*>::const_iterator i = i_transports.begin(); i != i_transports.end(); ++i)
sLog.outString(">>>%s initialized", (*i)->GetGuidStr().c_str());
*/
sLog.outString(">> Loaded " SIZEFMTD " local transports for map %u", i_transports.size(), GetId());
}
void MapManager::LoadTransports()
{
QueryResult* result = WorldDatabase.Query("SELECT entry, name, period FROM transports");
@ -44,7 +73,7 @@ void MapManager::LoadTransports()
{
BarGoLink bar(1);
bar.step();
sLog.outString(">> Loaded %u transports", count);
sLog.outString(">> Loaded 0 global transports");
sLog.outString();
return;
}
@ -55,73 +84,28 @@ void MapManager::LoadTransports()
{
bar.step();
Transport* t = new Transport;
Field* fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
uint32 entry = fields[0].GetUInt32();
std::string name = fields[1].GetCppString();
t->m_period = fields[2].GetUInt32();
uint32 period = fields[2].GetUInt32();
const GameObjectInfo* goinfo = ObjectMgr::GetGameObjectInfo(entry);
if (!goinfo)
{
sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template missing", entry, name.c_str());
delete t;
continue;
}
if (goinfo->type != GAMEOBJECT_TYPE_MO_TRANSPORT)
{
sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template type wrong", entry, name.c_str());
delete t;
continue;
}
// sLog.outString("Loading transport %d between %s, %s", entry, name.c_str(), goinfo->name);
std::set<uint32> mapsUsed;
if (!t->GenerateWaypoints(goinfo->moTransport.taxiPathId, mapsUsed))
// skip transports with empty waypoints list
{
sLog.outErrorDb("Transport (path id %u) path size = 0. Transport ignored, check DBC files or transport GO data0 field.", goinfo->moTransport.taxiPathId);
delete t;
continue;
}
float x, y, z, o;
uint32 mapid;
x = t->m_WayPoints[0].x; y = t->m_WayPoints[0].y; z = t->m_WayPoints[0].z; mapid = t->m_WayPoints[0].mapid; o = 1;
// current code does not support transports in dungeon!
const MapEntry* pMapInfo = sMapStore.LookupEntry(mapid);
if (!pMapInfo || pMapInfo->Instanceable())
GlobalTransport* t = new GlobalTransport();
if (!t->Initialize(entry, period, name))
{
delete t;
continue;
}
// creates the Gameobject
if (!t->Create(entry, mapid, x, y, z, o, GO_ANIMPROGRESS_DEFAULT))
{
delete t;
continue;
}
for (std::set<uint32>::const_iterator i = t->GetMapsUsed()->begin(); i != t->GetMapsUsed()->end(); ++i)
{ m_TransportsByMap[*i].insert(t); }
m_Transports.insert(t);
for (std::set<uint32>::const_iterator i = mapsUsed.begin(); i != mapsUsed.end(); ++i)
{ m_TransportsByMap[*i].insert(t); }
// If we someday decide to use the grid to track transports, here:
t->SetMap(sMapMgr.CreateMap(mapid, t));
// t->GetMap()->Add<GameObject>((GameObject *)t);
++count;
}
while (result->NextRow());
delete result;
// check transport data DB integrity
@ -142,54 +126,195 @@ void MapManager::LoadTransports()
delete result;
}
sLog.outString(">> Loaded %u transports", count);
sLog.outString();
for (std::set<Transport*>::const_iterator i = m_Transports.begin(); i != m_Transports.end(); ++i)
sLog.outString(">>>Global transporter %s (id = %u) initialized", (*i)->GetName(), (*i)->GetEntry());
sLog.outString(">> Loaded %u global transports", count);
}
//*****************************//
// Base Transport
//*****************************//
Transport::Transport() : GameObject()
{
m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_ALL | UPDATEFLAG_HAS_POSITION);
}
bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress)
Transport::~Transport()
{
Relocate(x, y, z, ang);
}
bool Transport::AddPassenger(Unit* passenger)
{
if (m_passengers.find(passenger) == m_passengers.end())
{
DETAIL_LOG("%s boarded transport %s.", passenger->GetGuidStr().c_str(), GetName());
m_passengers.insert(passenger);
}
return true;
}
bool Transport::RemovePassenger(Unit* passenger)
{
if (m_passengers.erase(passenger))
{ DETAIL_LOG("%s removed from transport %s.", passenger->GetGuidStr().c_str(), GetName()); }
return true;
}
//*****************************//
// LocalTransport
//*****************************//
LocalTransport::LocalTransport() : Transport()
{
}
LocalTransport::~LocalTransport()
{
//sLog.outString("Deleting %s, map %u", GetGuidStr().c_str(), GetMap()->GetId());
}
bool LocalTransport::Initialize(uint32 guid, Map* m)
{
if (m == NULL)
{ return false; }
GameObjectData const* gdata = sObjectMgr.GetGOData(guid);
if (!gdata)
{
sLog.outErrorDb("Local transport GUID %u does not exist into `gameobject` table", guid);
return false;
}
GameObjectInfo const* goinfo = ObjectMgr::GetGameObjectInfo(gdata->id);
if (goinfo->type != GAMEOBJECT_TYPE_TRANSPORT)
{
sLog.outErrorDb("Local transport GUID:%u, Name:%s, Entry:%u will not be loaded, `gameobject_template` type record is wrong", guid, goinfo->name, goinfo->id);
return false;
}
Object::_Create(guid, goinfo->id, HIGHGUID_TRANSPORT);
float r0, r1, r2, r3;
r0 = gdata->rotation0;
r1 = gdata->rotation1;
r2 = gdata->rotation2;
r3 = gdata->rotation3;
if (r0 == 0.0f && r1 == 0.0f && r2 == 0.0f) //TODO make a method for this
{
r2 = sin(gdata->orientation/2);
r3 = cos(gdata->orientation/2);
}
G3D::Quat q(r0, r1, r2, r3);
q.unitize();
float o = GetOrientationFromQuat(q);
SetMap(m);
Relocate(gdata->posX, gdata->posY, gdata->posZ, o);
if (!IsPositionValid())
{
sLog.outError("Transport (GUID: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)",
guidlow, x, y);
sLog.outError("Local transport GUID:%u, Name:%s, Entry:%u not created. Suggested coordinates are not valid: (X, Y, Z)=(%f, %f, %f)",
guid, goinfo->name, goinfo->id, gdata->posX, gdata->posY, gdata->posZ);
return false;
}
Object::_Create(guidlow, 0, HIGHGUID_MO_TRANSPORT);
GameObjectInfo const* goinfo = ObjectMgr::GetGameObjectInfo(guidlow);
if (!goinfo)
{
sLog.outErrorDb("Transport not created: entry in `gameobject_template` not found, guidlow: %u map: %u (X: %f Y: %f Z: %f) ang: %f", guidlow, mapid, x, y, z, ang);
return false;
}
m_goInfo = goinfo;
SetQuaternion(q);
SetGOInfo(goinfo);
SetObjectScale(goinfo->size);
SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction);
SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
SetGoType(GAMEOBJECT_TYPE_TRANSPORT);
SetEntry(goinfo->id);
//SetDisplayId(goinfo->displayId);
// Use SetDisplayId only if we have the GO assigned to a proper map!
SetFloatValue(GAMEOBJECT_POS_X, gdata->posX);
SetFloatValue(GAMEOBJECT_POS_Y, gdata->posY);
SetFloatValue(GAMEOBJECT_POS_Z, gdata->posZ);
SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction);
SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId);
SetGoState(GO_STATE_READY);
SetGoType(GameobjectTypes(goinfo->type));
SetGoAnimProgress(GO_ANIMPROGRESS_DEFAULT);
SetName(goinfo->name);
return true;
}
SetGoAnimProgress(animprogress);
//*****************************//
// GlobalTransport
//*****************************//
GlobalTransport::GlobalTransport() : Transport()
{
}
GlobalTransport::~GlobalTransport()
{
}
bool GlobalTransport::Initialize(uint32 entry, uint32 period, std::string const& name)
{
const GameObjectInfo* goinfo = ObjectMgr::GetGameObjectInfo(entry);
if (!goinfo)
{
sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template missing", entry, name.c_str());
return false;
}
if (goinfo->type != GAMEOBJECT_TYPE_MO_TRANSPORT)
{
sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template type wrong", entry, name.c_str());
return false;
}
m_period = period;
SetGOInfo(goinfo); //order is important. GenerateWaypoints needs m_goInfo access
if (!GenerateWaypoints())
{
sLog.outErrorDb("Transport (path id %u) path size = 0. Transport ignored, check DBC files or transport GO data0 field.", goinfo->moTransport.taxiPathId);
return false;
}
uint32 mapid = m_WayPoints[0].mapid;
// no global transports in dungeons
const MapEntry* pMapInfo = sMapStore.LookupEntry(mapid);
if (!pMapInfo || pMapInfo->Instanceable())
{
return false;
}
Map* m = sMapMgr.CreateMap(mapid, this);
if (m == NULL)
{
return false;
}
float x = m_WayPoints[0].x;
float y = m_WayPoints[0].y;
float z = m_WayPoints[0].z;
float o = 0.0f;
SetMap(m);
Relocate(x, y, z, o);
if (!IsPositionValid())
{
sLog.outError("Transport ID:%u not created. Suggested coordinates are not valid: (X, Y, Z)=(%f, %f, %f)", goinfo->id, x, y, z);
return false;
}
Object::_Create(goinfo->id, 0, HIGHGUID_MO_TRANSPORT);
SetObjectScale(goinfo->size);
SetGoType(GAMEOBJECT_TYPE_MO_TRANSPORT);
SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction);
SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
SetEntry(goinfo->id);
SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId);
SetGoState(GO_STATE_READY);
SetGoAnimProgress(GO_ANIMPROGRESS_DEFAULT);
SetName(goinfo->name);
return true;
@ -210,16 +335,21 @@ struct keyFrame
float tFrom, tTo;
};
bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32>& mapids)
bool GlobalTransport::GenerateWaypoints()
{
uint32 pathid = GetGOInfo()->moTransport.taxiPathId;
if (pathid >= sTaxiPathNodesByPath.size())
{ return false; }
{
return false;
}
TaxiPathNodeList const& path = sTaxiPathNodesByPath[pathid];
std::vector<keyFrame> keyFrames;
int mapChange = 0;
mapids.clear();
m_mapsUsed.clear();
for (size_t i = 1; i < path.size() - 1; ++i)
{
if (mapChange == 0)
@ -229,7 +359,7 @@ bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32>& mapids)
{
keyFrame k(node_i);
keyFrames.push_back(k);
mapids.insert(k.node->mapid);
m_mapsUsed.insert(k.node->mapid);
}
else
{
@ -428,7 +558,7 @@ bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32>& mapids)
return true;
}
void Transport::MoveToNextWayPoint()
void GlobalTransport::MoveToNextWayPoint()
{
m_curr = m_next;
@ -437,40 +567,35 @@ void Transport::MoveToNextWayPoint()
{ m_next = m_WayPoints.begin(); }
}
void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z)
void GlobalTransport::TeleportTransport(uint32 newMapid, float x, float y, float z)
{
Map const* oldMap = GetMap();
Map* newMap = sMapMgr.CreateMap(newMapid, this);
SetMap(newMap);
Relocate(x, y, z);
for (PlayerSet::iterator itr = m_passengers.begin(); itr != m_passengers.end();)
for (UnitSet::iterator itr = m_passengers.begin(); itr != m_passengers.end();)
{
PlayerSet::iterator it2 = itr;
UnitSet::iterator it2 = itr;
++itr;
Player* plr = *it2;
if (!plr)
Unit* unit = *it2;
if (!unit)
{
m_passengers.erase(it2);
continue;
}
if (plr->IsDead() && !plr->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
if (Player* plr = unit->ToPlayer())
{
plr->ResurrectPlayer(1.0);
if (plr->IsDead() && !plr->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
{
plr->ResurrectPlayer(1.0);
}
plr->TeleportTo(newMapid, x, y, z, GetOrientation(), TELE_TO_NOT_LEAVE_TRANSPORT);
}
plr->TeleportTo(newMapid, x, y, z, GetOrientation(), TELE_TO_NOT_LEAVE_TRANSPORT);
// WorldPacket data(SMSG_811, 4);
// data << uint32(0);
// plr->GetSession()->SendPacket(&data);
}
// we need to create and save new Map object with 'newMapid' because if not done -> lead to invalid Map object reference...
// player far teleport would try to create same instance, but we need it NOW for transport...
// correct me if I'm wrong O.o
Map* newMap = sMapMgr.CreateMap(newMapid, this);
SetMap(newMap);
if (oldMap != newMap)
{
UpdateForMap(oldMap);
@ -478,24 +603,7 @@ void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z)
}
}
bool Transport::AddPassenger(Player* passenger)
{
if (m_passengers.find(passenger) == m_passengers.end())
{
DETAIL_LOG("Player %s boarded transport %s.", passenger->GetName(), GetName());
m_passengers.insert(passenger);
}
return true;
}
bool Transport::RemovePassenger(Player* passenger)
{
if (m_passengers.erase(passenger))
{ DETAIL_LOG("Player %s removed from transport %s.", passenger->GetName(), GetName()); }
return true;
}
void Transport::Update(uint32 /*update_diff*/, uint32 /*p_time*/)
void GlobalTransport::Update(uint32 /*update_diff*/, uint32 /*p_time*/)
{
if (m_WayPoints.size() <= 1)
{ return; }
@ -515,15 +623,6 @@ void Transport::Update(uint32 /*update_diff*/, uint32 /*p_time*/)
Relocate(m_curr->second.x, m_curr->second.y, m_curr->second.z);
}
/*
for(PlayerSet::const_iterator itr = m_passengers.begin(); itr != m_passengers.end();)
{
PlayerSet::const_iterator it2 = itr;
++itr;
//(*it2)->SetPosition( m_curr->second.x + (*it2)->GetTransOffsetX(), m_curr->second.y + (*it2)->GetTransOffsetY(), m_curr->second.z + (*it2)->GetTransOffsetZ(), (*it2)->GetTransOffsetO() );
}
*/
m_nextNodeTime = m_curr->first;
if (m_curr == m_WayPoints.begin())
@ -533,7 +632,7 @@ void Transport::Update(uint32 /*update_diff*/, uint32 /*p_time*/)
}
}
void Transport::UpdateForMap(Map const* targetMap)
void GlobalTransport::UpdateForMap(Map const* targetMap)
{
Map::PlayerList const& pl = targetMap->GetPlayers();
if (pl.isEmpty())

View File

@ -31,19 +31,57 @@
#include <set>
#include <string>
typedef std::set<Unit*> UnitSet;
//Base class for all transporter types
class Transport : public GameObject
{
public:
explicit Transport();
virtual ~Transport();
bool Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress);
bool GenerateWaypoints(uint32 pathid, std::set<uint32>& mapids);
void Update(uint32 update_diff, uint32 p_time) override;
bool AddPassenger(Player* passenger);
bool RemovePassenger(Player* passenger);
bool AddPassenger(Unit* passenger);
bool RemovePassenger(Unit* passenger);
typedef std::set<Player*> PlayerSet;
PlayerSet const& GetPassengers() const { return m_passengers; }
virtual void Update(uint32 update_diff, uint32 p_time) = 0;
virtual void DeleteFromDB() override {}
UnitSet const& GetPassengers() const { return m_passengers; }
protected:
UnitSet m_passengers;
};
class LocalTransport : public Transport
{
public:
explicit LocalTransport();
virtual ~LocalTransport();
bool Initialize(uint32 guid, Map* m);
virtual void Update(uint32 update_diff, uint32 p_time) override {} //NYI
private:
uint32 m_period;
};
class GlobalTransport : public Transport
{
public:
explicit GlobalTransport();
virtual ~GlobalTransport();
virtual void Update(uint32 update_diff, uint32 p_time) override;
bool Initialize(uint32 entry, uint32 period, std::string const& name);
std::set<uint32> const* GetMapsUsed() const { return &m_mapsUsed; }
private:
bool GenerateWaypoints();
void TeleportTransport(uint32 newMapid, float x, float y, float z);
void UpdateForMap(Map const* map);
void MoveToNextWayPoint(); // move m_next/m_cur to next points
private:
struct WayPoint
@ -60,21 +98,15 @@ class Transport : public GameObject
typedef std::map<uint32, WayPoint> WayPointMap;
WayPointMap m_WayPoints;
WayPointMap::const_iterator m_curr;
WayPointMap::const_iterator m_next;
std::set<uint32> m_mapsUsed;
uint32 m_pathTime;
uint32 m_timer;
PlayerSet m_passengers;
public:
WayPointMap m_WayPoints;
uint32 m_nextNodeTime;
uint32 m_period;
private:
void TeleportTransport(uint32 newMapid, float x, float y, float z);
void UpdateForMap(Map const* map);
void MoveToNextWayPoint(); // move m_next/m_cur to next points
};
#endif

View File

@ -1349,9 +1349,6 @@ void World::SetInitialWorldSettings()
sLog.outString("Starting Outdoor PvP System");
sOutdoorPvPMgr.InitOutdoorPvP();
// Not sure if this can be moved up in the sequence (with static data loading) as it uses MapManager
sLog.outString("Loading Transports...");
sMapMgr.LoadTransports();
// Initialize Warden
sLog.outString("Loading Warden Checks...");
@ -1377,8 +1374,12 @@ void World::SetInitialWorldSettings()
m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent); // depend on next event
sLog.outString();
sLog.outString("Loading grids for active creatures or transports...");
sObjectMgr.LoadActiveEntities(NULL);
sLog.outString("Loading grids for active creatures and local transports...");
sMapMgr.LoadContinents();
sLog.outString();
sLog.outString("Loading global transports...");
sMapMgr.LoadTransports();
sLog.outString();
// Delete all characters which have been deleted X days before

View File

@ -1,60 +0,0 @@
# MaNGOS is a full featured server for World of Warcraft, supporting
# the following clients: 1.12.x, 2.4.3, 3.2.5a, 4.2.3 and 5.4.8
#
# Copyright (C) 2005-2016 MaNGOS project <https://getmangos.eu>
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ***** END GPL LICENSE BLOCK *****
#
# World of Warcraft, and all World of Warcraft or Warcraft art, images,
# and lore are copyrighted by Blizzard Entertainment, Inc.
include(MacroMangosSourceGroup)
#-----------------------------------------------------------------------------
# Define the movement library
file(GLOB sources *.cpp)
file(GLOB headers *.h)
set(movement_LIB_SRCS ${sources} ${headers})
mangos_source_group(${movement_LIB_SRCS})
include_directories(
${ACE_INCLUDE_DIRS}
${MYSQL_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/dep/include/g3dlite/
${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include/
${CMAKE_SOURCE_DIR}/src/framework/
${CMAKE_SOURCE_DIR}/src/shared/
${CMAKE_SOURCE_DIR}/src/game/
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}/src/shared/
)
#-----------------------------------------------------------------------------
# Build the movement library
add_library(mangos-movement STATIC ${movement_LIB_SRCS})
target_link_libraries(mangos-movement mangos-shared mangos-framework Detour g3dlite ${ACE_LIBRARIES} ${MYSQL_LIBRARIES})
if(${CMAKE_BUILD_TYPE} MATCHES Debug)
set(BUILD_PROPERTIES "-DMANGOS_DEBUG")
set_target_properties(mangos-movement PROPERTIES COMPILE_FLAGS ${BUILD_PROPERTIES})
endif()

View File

@ -1,59 +0,0 @@
# MaNGOS is a full featured server for World of Warcraft, supporting
# the following clients: 1.12.x, 2.4.3, 3.2.5a, 4.2.3 and 5.4.8
#
# Copyright (C) 2005-2016 MaNGOS project <https://getmangos.eu>
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ***** END GPL LICENSE BLOCK *****
#
# World of Warcraft, and all World of Warcraft or Warcraft art, images,
# and lore are copyrighted by Blizzard Entertainment, Inc.
include(MacroMangosSourceGroup)
#-----------------------------------------------------------------------------
# Define the vmap library
file(GLOB sources *.cpp)
file(GLOB headers *.h)
set(vmap_LIB_SRCS ${sources} ${headers})
mangos_source_group(${vmap_LIB_SRCS})
include_directories(
${ACE_INCLUDE_DIRS}
${MYSQL_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/dep/g3dlite/
${CMAKE_SOURCE_DIR}/src/framework/
${CMAKE_SOURCE_DIR}/src/shared/
${CMAKE_SOURCE_DIR}/src/game/
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}/src/shared/
)
#-----------------------------------------------------------------------------
# Build the vmap library
add_library(mangos-vmap STATIC ${vmap_LIB_SRCS})
target_link_libraries(mangos-vmap mangos-shared mangos-framework g3dlite ${ACE_LIBRARIES} ${MYSQL_LIBRARIES})
if(${CMAKE_BUILD_TYPE} MATCHES Debug)
set(BUILD_PROPERTIES "-DMANGOS_DEBUG")
set_target_properties(mangos-vmap PROPERTIES COMPILE_FLAGS ${BUILD_PROPERTIES})
endif()

View File

@ -192,7 +192,7 @@ bool GameObjectModel::GetIntersectPoint(const G3D::Vector3& srcPoint, G3D::Vecto
{
G3D::Vector3 p;
if (absolute)
p = (iQuat * G3D::Quat((srcPoint - iPos) * iInvScale) * iQuat.conj()).imag();
p = (iQuat.conj() * G3D::Quat((srcPoint - iPos) * iInvScale) * iQuat).imag();
else
p = srcPoint;

@ -1 +1 @@
Subproject commit 4aba0d6da2f637cee2c3eb0c7b6f255cf6fe0aa9
Subproject commit 57214b69c71d6a0d5ff2a353b4e3f8881317fe86

@ -1 +1 @@
Subproject commit f52ae4ad1e5baddb4dd9476e81fe177ab9ca5f4f
Subproject commit 888c9c332d3251adf7b9945a89ba44a16c84486d