Index: shared/Database/DBCfmt.cpp =================================================================== --- shared/Database/DBCfmt.cpp (revision 5322) +++ shared/Database/DBCfmt.cpp (working copy) @@ -65,5 +65,5 @@ const char TaxiPathEntryfmt[]="niii"; const char TaxiPathNodeEntryfmt[]="diiifffiixx"; const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii"; -const char WorldMapAreaEntryfmt[]="xxnxffffx"; +const char WorldMapAreaEntryfmt[]="xinxffffi"; const char WorldSafeLocsEntryfmt[]="nifffxxxxxxxxxxxxxxxxx"; Index: shared/Database/DBCStores.cpp =================================================================== --- shared/Database/DBCStores.cpp (revision 5322) +++ shared/Database/DBCStores.cpp (working copy) @@ -519,6 +519,21 @@ std::swap(x,y); // client have map coords swapped } +uint32 GetZoneVirtualMap(uint32 nZoneId) +{ + if (nZoneId == 0) + return static_cast(-1); + + WorldMapAreaEntry const * wma = sWorldMapAreaStore.LookupEntry(nZoneId); + + if (wma) + return (wma->virtual_map_id != -1) ? static_cast(wma->virtual_map_id) : wma->map_id; + + MapEntry const * map = sMapStore.LookupEntry(nZoneId); + + return map ? map->parent_map : static_cast(-1); +} + uint32 GetTalentInspectBitPosInTab(uint32 talentId) { TalentInspectMap::const_iterator itr = sTalentPosInInspect.find(talentId); Index: shared/Database/DBCStructure.h =================================================================== --- shared/Database/DBCStructure.h (revision 5322) +++ shared/Database/DBCStructure.h (working copy) @@ -654,14 +654,14 @@ struct WorldMapAreaEntry { //uint32 ID; // 0 - //uint32 map_id; // 1 + uint32 map_id; // 1 uint32 area_id; // 2 index (continent 0 areas ignored) //char* internal_name // 3 float y1; // 4 float y2; // 5 float x1; // 6 float x2; // 7 - //int32 virtual_map_id; // 8 -1 (map_id have correct map) other: virtual map where zone show (map_id - where zone in fact internally) + int32 virtual_map_id; // 8 -1 (map_id have correct map) other: virtual map where zone show (map_id - where zone in fact internally) }; struct WorldSafeLocsEntry Index: shared/Database/DBCStores.h =================================================================== --- shared/Database/DBCStores.h (revision 5322) +++ shared/Database/DBCStores.h (working copy) @@ -40,6 +40,7 @@ void Zone2MapCoordinates(float& x,float& y,uint32 zone); void Map2ZoneCoordinates(float& x,float& y,uint32 zone); +uint32 GetZoneVirtualMap(uint32 nZoneId); uint32 GetTalentInspectBitPosInTab(uint32 talentId); uint32 GetTalentTabInspectBitSize(uint32 talentTabId); Index: game/Formulas.h =================================================================== --- game/Formulas.h (revision 5322) +++ game/Formulas.h (working copy) @@ -69,17 +69,18 @@ return 17; } - inline uint32 BaseGain(uint32 pl_level, uint32 mob_level) + inline uint32 BaseGain(uint32 pl_level, uint32 mob_level, ZoneOriginType eOrigin) { + const uint32 nBaseExp = (eOrigin == ZONE_ORIGIN_OUTLAND) ? 235 : 45; if( mob_level >= pl_level ) - return ((pl_level*5 + 45) * (20 + mob_level - pl_level)/10 + 1)/2; + return ((pl_level*5 + nBaseExp) * (20 + mob_level - pl_level)/10 + 1)/2; else { uint32 gray_level = GetGrayLevel(pl_level); if( mob_level > gray_level ) { uint32 ZD = GetZeroDifference(pl_level); - return (pl_level*5 + 45) * (ZD + mob_level - pl_level)/ZD; + return (pl_level*5 + nBaseExp) * (ZD + mob_level - pl_level)/ZD; } return 0; } @@ -90,7 +91,7 @@ if(u->GetTypeId()==TYPEID_UNIT && ((Creature*)u)->isTotem() || ((Creature*)u)->isPet()) return 0; - uint32 xp_gain= BaseGain(pl->getLevel(), u->getLevel()); + uint32 xp_gain= BaseGain(pl->getLevel(), u->getLevel(), Map::GetZoneOrigin(u->GetZoneId(), u->GetMapId())); if( xp_gain == 0 ) return 0; Index: game/Map.h =================================================================== --- game/Map.h (revision 5322) +++ game/Map.h (working copy) @@ -114,6 +114,13 @@ #define MAX_HEIGHT 100000.0f // can be use for find ground height at surface #define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE +enum ZoneOriginType +{ + ZONE_ORIGIN_UNKNOWN = 0, + ZONE_ORIGIN_AZEROTH = 1, + ZONE_ORIGIN_OUTLAND = 2 +}; + class MANGOS_DLL_DECL Map : public GridRefManager, public MaNGOS::ObjectLevelLockable { public: @@ -180,6 +187,7 @@ static uint32 GetAreaId(uint16 areaflag); static uint32 GetZoneId(uint16 areaflag); + static ZoneOriginType GetZoneOrigin(uint32 nZoneId, uint32 nRealMapId = static_cast(-1)); uint32 GetAreaId(float x, float y) const { @@ -229,6 +237,8 @@ bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); } void markCell(uint32 pCellId) { marked_cells.set(pCellId); } private: + static ZoneOriginType ComputeZoneOrigin(uint32 nZoneId, uint32 nRealMapId); + void LoadVMap(int pX, int pY); void LoadMap(uint32 mapid, uint32 instanceid, int x,int y); @@ -281,6 +291,8 @@ typedef GridReadGuard ReadGuard; typedef GridWriteGuard WriteGuard; + static std::map sm_ZoneOriginCache; + uint32 i_id; NGridType* i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; GridMap *GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; Index: game/Unit.cpp =================================================================== --- game/Unit.cpp (revision 5322) +++ game/Unit.cpp (working copy) @@ -718,7 +718,8 @@ if(pet->GetTypeId()==TYPEID_UNIT && ((Creature*)pet)->isPet()) { - uint32 petxp = MaNGOS::XP::BaseGain(getLevel(), pVictim->getLevel()); + uint32 petxp = MaNGOS::XP::BaseGain(getLevel(), pVictim->getLevel(), + PvP ? ZONE_ORIGIN_UNKNOWN : Map::GetZoneOrigin(pVictim->GetZoneId(), pVictim->GetMapId())); ((Pet*)pet)->GivePetXP(petxp); } } Index: game/Map.cpp =================================================================== --- game/Map.cpp (revision 5322) +++ game/Map.cpp (working copy) @@ -44,6 +44,8 @@ GridState* si_GridStates[MAX_GRID_STATE]; +std::map Map::sm_ZoneOriginCache; + Map::~Map() { UnloadAll(true); @@ -1256,6 +1258,56 @@ return 0; } +ZoneOriginType Map::GetZoneOrigin(uint32 nZoneId, uint32 nRealMapId) +{ + ZoneOriginType eZoneOrigin = ZONE_ORIGIN_UNKNOWN; + + std::map::const_iterator pos = sm_ZoneOriginCache.find(nZoneId); + if (pos != sm_ZoneOriginCache.end()) + { + eZoneOrigin = pos->second; + } + else + { + eZoneOrigin = ComputeZoneOrigin(nZoneId, nRealMapId); + sm_ZoneOriginCache.insert(std::map::value_type(nZoneId, eZoneOrigin)); + } + + return eZoneOrigin; +} + +ZoneOriginType Map::ComputeZoneOrigin(uint32 nZoneId, uint32 nRealMapId) +{ + if (nRealMapId == static_cast(-1)) + { + AreaTableEntry const * area = GetAreaEntryByAreaID(nZoneId); + + if (!area) + return ZONE_ORIGIN_UNKNOWN; + + nRealMapId = area->mapid; + } + + switch (nRealMapId) + { + case 550: // Tempest Keep: The Eye + case 552: // Tempest Keep: The Arcatraz + case 553: // Tempest Keep: The Botanica + case 554: // Tempest Keep: The Mechanar + case 559: // Nagrand Arena + case 562: // Blade's Edge Arena + case 566: // Eye of the Storm + return ZONE_ORIGIN_OUTLAND; + } + + uint32 nVirtualMapId = GetZoneVirtualMap(nZoneId); + + if (nVirtualMapId == static_cast(-1)) + nVirtualMapId = nRealMapId; + + return (nVirtualMapId == 530) ? ZONE_ORIGIN_OUTLAND : ZONE_ORIGIN_AZEROTH; +} + bool Map::IsInWater(float x, float y, float pZ) const { // This method is called too often to use vamps for that (4. parameter = false).