aboutsummaryrefslogtreecommitdiff
path: root/src/game/Map.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/Map.cpp')
-rw-r--r--src/game/Map.cpp340
1 files changed, 132 insertions, 208 deletions
diff --git a/src/game/Map.cpp b/src/game/Map.cpp
index 53efb35e373..f8e48d3a326 100644
--- a/src/game/Map.cpp
+++ b/src/game/Map.cpp
@@ -1746,220 +1746,105 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const
}
}
-float Map::GetVmapHeight(float x, float y, float z) const
+inline bool IsOutdoorWMO(uint32 mogpFlags, int32 adtId, int32 rootId, int32 groupId, WMOAreaTableEntry const* wmoEntry, AreaTableEntry const* atEntry)
{
- float mapHeight;
-
- mapHeight = GetHeight(x, y, z, false);
- if (fabs(mapHeight - z) < 0.1)
- return mapHeight;
+ bool outdoor = true;
- VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
- if (!vmgr->isLineOfSightCalcEnabled())
- return mapHeight;
+ if(wmoEntry && atEntry)
+ {
+ if(atEntry->flags & AREA_FLAG_OUTSIDE)
+ return true;
+ if(atEntry->flags & AREA_FLAG_INSIDE)
+ return false;
+ }
- float vmapHeight = vmgr->getHeight(GetId(), x, y, z + 2.0f, z + 2.0f - mapHeight);
- if (vmapHeight > VMAP_INVALID_HEIGHT_VALUE)
- return vmapHeight;
+ outdoor = mogpFlags&0x8;
- return mapHeight;
+ if(wmoEntry)
+ {
+ if(wmoEntry->Flags & 4)
+ return true;
+ if((wmoEntry->Flags & 2)!=0)
+ outdoor = false;
+ }
+ return outdoor;
}
-uint16 Map::GetAreaFlag(float x, float y, float z) const
+bool Map::IsOutdoors(float x, float y, float z) const
{
- uint16 areaflag;
- if (GridMap *gmap = const_cast<Map*>(this)->GetGrid(x, y))
- areaflag = gmap->getArea(x, y);
- // this used while not all *.map files generated (instances)
- else
- areaflag = GetAreaFlagByMapId(GetId());
-
- //FIXME: some hacks for areas above or underground for ground area
- // required for area specific spells/etc, until map/vmap data
- // not provided correct areaflag with this hacks
- switch(areaflag)
- {
- case 2817: // Argent Tournament Grounds (Icecrown)
- if (x < 8445.0f && x > 8390.0f && y > 640.0f && y < 689.0f && 548.0f < z && z < 562.0f)
- areaflag = 2875; // Sunreaver Pavilion (Icecrown)
- else if (x > 8587.0f && x < 8629.0f && y > 646.0f && y < 686.0f && 548.0f < z && z < 562.0f)
- areaflag = 2879; // Silver Covenant Pavilion (Icecrown)
- break;
- case 2227: // The Foot Steppes (Storm Peaks)
- case 2207: // Sifreldar Village (Storm Peaks)
- if (6924.0f < x && x < 6980.0f && -1520.0f < y && y < -1432.0f && 838.0f < z && z < 843.0f)
- areaflag = 2213; // The Forlorn Mine (Storm Peaks)
- break;
- case 2209: // Brunnhildar Village (Storm Peaks)
- if (6885.0f < x && x < 6938.0f && -1200.0f < y && y < -1138.0f && 801.0f < z && z < 809.0f)
- areaflag = 2213; // The Forlorn Mine (Storm Peaks)
- break;
- case 166: // Storm Peaks
- if (6812.0f < x && x < 7048.0f && -1463.0f < y && y < -1200.0f && 807.0f < z && z < 843.0f)
- areaflag = 2213; // The Forlorn Mine (Storm Peaks)
- break;
- case 446: // (Stonelaton Mountains)
- case 944: // Boulderslide Ravine (Stonelaton Mountains)
- if (-128.0f < x && x < 35.0f && 221.0f < y && y < 456.0f && 87.0f < z && z < 130.0f)
- areaflag = 1019; // Boulderslide Cavern (Stonelaton Mountains)
- break;
- case 272: // Palemane Rock (Mulgore)
- if (-2466.0f < x && x < -2295.0f && 366.0f < y && y < 530.0f && 40.0f < z && z < 70.0f)
- areaflag = 668; // Palemane Rock (Mulgore)
- break;
- case 65535: // Multipe places.
- if (-128.0f < x && x < 35.0f && 221.0f < y && y < 456.0f && 87.0f < z && z < 130.0f)
- areaflag = 1019; // Boulderslide Cavern (Stonelaton Mountains)
- else if (-2466.0f < x && x < -2295.0f && 366.0f < y && y < 530.0f && 40.0f < z && z < 70.0f)
- areaflag = 668; // Palemane Rock (Mulgore)
- break;
- // Acherus: The Ebon Hold (Plaguelands: The Scarlet Enclave)
- case 1984: // Plaguelands: The Scarlet Enclave
- case 2076: // Death's Breach (Plaguelands: The Scarlet Enclave)
- case 2745: // The Noxious Pass (Plaguelands: The Scarlet Enclave)
- if (z > 350.0f) areaflag = 2048; break;
- // Acherus: The Ebon Hold (Eastern Plaguelands)
- case 856: // The Noxious Glade (Eastern Plaguelands)
- case 2456: // Death's Breach (Eastern Plaguelands)
- if (z > 350.0f) areaflag = 1950; break;
- // Dalaran
- case 2492: // Forlorn Woods (Crystalsong Forest)
- case 2371: // Valley of Echoes (Icecrown Glacier)
- if (x > 5568.0f && x < 6022.0f && y > 374.0f && y < 918.0f && z > 563.0f)
- {
- areaflag = 2153;
- if (y - 1.41f * x + 7649.55f > 0) // Violet Hold
- {
- if (y < 595.0f)
- areaflag = 2540;
- }
- else if (y + 2.91 * x - 17522.57f < 0) // Krasus landing
- areaflag = 2531;
- }
- break;
- // The Violet Citadel (Dalaran) or Dalaran
- case 2484: // The Twilight Rivulet (Crystalsong Forest)
- case 1593: // Crystalsong Forest
- // Dalaran
- if (x > 5568.0f && x < 6116.0f && y > 282.0f && y < 918.0f && z > 563.0f)
- {
- // The Violet Citadel (Dalaran), fast check
- if (x > 5721.1f && x < 5884.66f && y > 764.4f && y < 948.0f)
- {
- // The Violet Citadel (Dalaran)
- if ((x-5803.0f)*(x-5803.0f)+(y-846.18f)*(y-846.18f) < 6690.0f)
- {
- areaflag = 2696;
- break;
- }
- }
+ uint32 mogpFlags;
+ int32 adtId, rootId, groupId;
- // The Eventide (Dalaran), fast check against diagonal box with lower limit
- if (z > 635.0f && x+y < 6375.0f && x+y > 6295.0f && x-y < 5106.0f && x-y > 4972.0f)
- {
- areaflag = 2543;
- break;
- }
+ // no wmo found? -> outside by default
+ if(!GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId))
+ return true;
- // The Violet Hold (Dalaran), fast check
- if (x < 5791.0f && y > 404.0f && y < 595.0f)
- {
- areaflag = 2540;
- break;
- }
+ AreaTableEntry const* atEntry = 0;
+ WMOAreaTableEntry const* wmoEntry= GetWMOAreaTableEntryByTripple(rootId, adtId, groupId);
+ if(wmoEntry)
+ {
+ DEBUG_LOG("Got WMOAreaTableEntry! flag %u, areaid %u", wmoEntry->Flags, wmoEntry->areaId);
+ atEntry = GetAreaEntryByAreaID(wmoEntry->areaId);
+ }
+ return IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry);
+}
- // Dalaran
- areaflag = 2153;
- }
- break;
- // Vargoth's Retreat (Dalaran) or The Violet Citadel (Dalaran) or Dalaran
- case 2504: // Violet Stand (Crystalsong Forest)
- // Dalaran
- if (x > 5568.0f && x < 6116.0f && y > 282.0f && y < 982.0f && z > 563.0f)
- {
- // The Violet Citadel (Dalaran), fast check
- if (x > 5721.1f && x < 5884.66f && y > 764.4f && y < 948.0f)
- {
- // Vargoth's Retreat (Dalaran), nice slow circle with upper limit
- if (z < 898.0f && (x-5765.0f)*(x-5765.0f)+(y-862.4f)*(y-862.4f) < 262.0f)
- {
- areaflag = 2748;
- break;
- }
+bool Map::GetAreaInfo(float x, float y, float z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const
+{
+ float vmap_z = z;
+ VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
+ if (vmgr->getAreaInfo(GetId(), x, y, vmap_z, flags, adtId, rootId, groupId))
+ {
+ // check if there's terrain between player height and object height
+ if(GridMap *gmap = const_cast<Map*>(this)->GetGrid(x, y))
+ {
+ float _mapheight = gmap->getHeight(x,y);
+ // z + 2.0f condition taken from GetHeight(), not sure if it's such a great choice...
+ if(z + 2.0f > _mapheight && _mapheight > vmap_z)
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
- // The Violet Citadel (Dalaran)
- if ((x-5803.0f)*(x-5803.0f)+(y-846.18f)*(y-846.18f) < 6690.0f)
- {
- areaflag = 2696;
- break;
- }
- }
+uint16 Map::GetAreaFlag(float x, float y, float z, bool *isOutdoors) const
+{
+ uint32 mogpFlags;
+ int32 adtId, rootId, groupId;
+ WMOAreaTableEntry const* wmoEntry = 0;
+ AreaTableEntry const* atEntry = 0;
+ bool haveAreaInfo = false;
- // Dalaran
- areaflag = 2153;
- }
- break;
- // Maw of Neltharion (cave)
- case 164: // Dragonblight
- case 1797: // Obsidian Dragonshrine (Dragonblight)
- if (x > 4364.0f && x < 4632.0f && y > 1545.0f && y < 1886.0f && z < 200.0f) areaflag = 1853; break;
- // Undercity (sewers enter and path)
- case 179: // Tirisfal Glades
- if (x > 1595.0f && x < 1699.0f && y > 535.0f && y < 643.5f && z < 30.5f) areaflag = 685; break;
- // Undercity (Royal Quarter)
- case 210: // Silverpine Forest
- case 316: // The Shining Strand (Silverpine Forest)
- case 438: // Lordamere Lake (Silverpine Forest)
- if (x > 1237.0f && x < 1401.0f && y > 284.0f && y < 440.0f && z < -40.0f) areaflag = 685; break;
- // Undercity (cave and ground zone, part of royal quarter)
- case 607: // Ruins of Lordaeron (Tirisfal Glades)
- // ground and near to ground (by city walls)
- if (z > 0.0f)
- {
- if (x > 1510.0f && x < 1839.0f && y > 29.77f && y < 433.0f) areaflag = 685;
- }
- // more wide underground, part of royal quarter
- else
- {
- if (x > 1299.0f && x < 1839.0f && y > 10.0f && y < 440.0f) areaflag = 685;
- }
- break;
- // The Makers' Perch (ground) and Makers' Overlook (ground and cave)
- case 1335: // Sholazar Basin
- // The Makers' Perch ground (fast box)
- if (x > 6100.0f && x < 6250.0f && y > 5650.0f && y < 5800.0f)
- {
- // nice slow circle
- if ((x-6183.0f)*(x-6183.0f)+(y-5717.0f)*(y-5717.0f) < 2500.0f)
- areaflag = 2189;
- }
- // Makers' Overlook (ground and cave)
- else if (x > 5634.48f && x < 5774.53f && y < 3475.0f && z > 300.0f)
- {
- if (y > 3380.26f || (y > 3265.0f && z < 360.0f))
- areaflag = 2187;
- }
- break;
- // The Makers' Perch (underground)
- case 2147: // The Stormwright's Shelf (Sholazar Basin)
- if (x > 6199.0f && x < 6283.0f && y > 5705.0f && y < 5817.0f && z < 38.0f) areaflag = 2189; break;
- // Makers' Overlook (deep cave)
- case 267: // Icecrown
- if (x > 5684.0f && x < 5798.0f && y > 3035.0f && y < 3367.0f && z < 358.0f) areaflag = 2187; break;
- // Wyrmrest Temple (Dragonblight)
- case 1814: // Path of the Titans (Dragonblight)
- case 1897: // The Dragon Wastes (Dragonblight)
- // fast box
- if (x > 3400.0f && x < 3700.0f && y > 130.0f && y < 420.0f)
- {
- // nice slow circle
- if ((x-3546.87f)*(x-3546.87f)+(y-272.71f)*(y-272.71f) < 19600.0f) areaflag = 1791;
- }
- break;
+ if (GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId))
+ {
+ haveAreaInfo = true;
+ if (wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId))
+ atEntry = GetAreaEntryByAreaID(wmoEntry->areaId);
+ }
+
+ uint16 areaflag;
+
+ if (atEntry)
+ areaflag = atEntry->exploreFlag;
+ else
+ {
+ if (GridMap *gmap = const_cast<Map*>(this)->GetGrid(x, y))
+ areaflag = gmap->getArea(x, y);
+ // this used while not all *.map files generated (instances)
+ else
+ areaflag = GetAreaFlagByMapId(i_mapEntry->MapID);
}
+ if (isOutdoors)
+ {
+ if (haveAreaInfo)
+ *isOutdoors = IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry);
+ else
+ *isOutdoors = true;
+ }
return areaflag;
-}
+ }
uint8 Map::GetTerrainType(float x, float y) const
{
@@ -1971,10 +1856,51 @@ uint8 Map::GetTerrainType(float x, float y) const
ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data) const
{
- if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
- return gmap->getLiquidStatus(x, y, z, ReqLiquidType, data);
- else
- return LIQUID_MAP_NO_WATER;
+ ZLiquidStatus result = LIQUID_MAP_NO_WATER;
+ VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
+ float liquid_level, ground_level = INVALID_HEIGHT;
+ uint32 liquid_type;
+ if (vmgr->GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type))
+ {
+ sLog.outDebug("getLiquidStatus(): vmap liquid level: %f ground: %f type: %u", liquid_level, ground_level, liquid_type);
+ // Check water level and ground level
+ if (liquid_level > ground_level && z > ground_level - 2)
+ {
+ // All ok in water -> store data
+ if (data)
+ {
+ data->type = liquid_type;
+ data->level = liquid_level;
+ data->depth_level = ground_level;
+ }
+
+ // For speed check as int values
+ int delta = int((liquid_level - z) * 10);
+
+ // Get position delta
+ if (delta > 20) // Under water
+ return LIQUID_MAP_UNDER_WATER;
+ if (delta > 0 ) // In water
+ return LIQUID_MAP_IN_WATER;
+ if (delta > -1) // Walk on water
+ return LIQUID_MAP_WATER_WALK;
+ result = LIQUID_MAP_ABOVE_WATER;
+ }
+ }
+
+ if(GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
+ {
+ LiquidData map_data;
+ ZLiquidStatus map_result = gmap->getLiquidStatus(x, y, z, ReqLiquidType, &map_data);
+ // Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER:
+ if (map_result != LIQUID_MAP_NO_WATER && (map_data.level > ground_level))
+ {
+ if (data)
+ *data = map_data;
+ return map_result;
+ }
+ }
+ return result;
}
float Map::GetWaterLevel(float x, float y) const
@@ -2013,17 +1939,15 @@ void Map::GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 area
zoneid = entry ? ((entry->zone != 0) ? entry->zone : entry->ID) : 0;
}
-bool Map::IsInWater(float x, float y, float pZ, float min_depth) const
+bool Map::IsInWater(float x, float y, float pZ, LiquidData *data) const
{
// Check surface in x, y point for liquid
if (const_cast<Map*>(this)->GetGrid(x, y))
{
LiquidData liquid_status;
- if (getLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, &liquid_status))
- {
- if (liquid_status.level - liquid_status.depth_level > min_depth)
+ LiquidData *liquid_ptr = data ? data : &liquid_status;
+ if (getLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr))
return true;
- }
}
return false;
}