// Get water state on map public ZLiquidStatus GetLiquidStatus(float x, float y, float z, uint ReqLiquidType, LiquidData data) { // Check water type (if no water return) if (_liquidGlobalFlags == 0 && _liquidFlags == null) { return(ZLiquidStatus.NoWater); } // Get cell float cx = MapConst.MapResolution * (32 - x / MapConst.SizeofGrids); float cy = MapConst.MapResolution * (32 - y / MapConst.SizeofGrids); int x_int = (int)cx & (MapConst.MapResolution - 1); int y_int = (int)cy & (MapConst.MapResolution - 1); // Check water type in cell int idx = (x_int >> 3) * 16 + (y_int >> 3); byte type = _liquidFlags != null ? _liquidFlags[idx] : _liquidGlobalFlags; uint entry = _liquidEntry != null ? _liquidEntry[idx] : _liquidGlobalEntry; LiquidTypeRecord liquidEntry = CliDB.LiquidTypeStorage.LookupByKey(entry); if (liquidEntry != null) { type &= (byte)MapConst.MapLiquidTypeDarkWater; uint liqTypeIdx = liquidEntry.SoundBank; if (entry < 21) { var area = CliDB.AreaTableStorage.LookupByKey(GetArea(x, y)); if (area != null) { uint overrideLiquid = area.LiquidTypeID[liquidEntry.SoundBank]; if (overrideLiquid == 0 && area.ParentAreaID == 0) { area = CliDB.AreaTableStorage.LookupByKey(area.ParentAreaID); if (area != null) { overrideLiquid = area.LiquidTypeID[liquidEntry.SoundBank]; } } var liq = CliDB.LiquidTypeStorage.LookupByKey(overrideLiquid); if (liq != null) { entry = overrideLiquid; liqTypeIdx = liq.SoundBank; } } } type |= (byte)(1 << (int)liqTypeIdx); } if (type == 0) { return(ZLiquidStatus.NoWater); } // Check req liquid type mask if (ReqLiquidType != 0 && !Convert.ToBoolean(ReqLiquidType & type)) { return(ZLiquidStatus.NoWater); } // Check water level: // Check water height map int lx_int = x_int - _liquidOffY; int ly_int = y_int - _liquidOffX; if (lx_int < 0 || lx_int >= _liquidHeight) { return(ZLiquidStatus.NoWater); } if (ly_int < 0 || ly_int >= _liquidWidth) { return(ZLiquidStatus.NoWater); } // Get water level float liquid_level = _liquidMap != null ? _liquidMap[lx_int * _liquidWidth + ly_int] : _liquidLevel; // Get ground level (sub 0.2 for fix some errors) float ground_level = GetHeight(x, y); // Check water level and ground level if (liquid_level < ground_level || z < ground_level - 2) { return(ZLiquidStatus.NoWater); } // All ok in water . store data if (data != null) { data.entry = entry; data.type_flags = type; data.level = liquid_level; data.depth_level = ground_level; } // For speed check as int values float delta = liquid_level - z; if (delta > 2.0f) // Under water { return(ZLiquidStatus.UnderWater); } if (delta > 0.0f) // In water { return(ZLiquidStatus.InWater); } if (delta > -0.1f) // Walk on water { return(ZLiquidStatus.WaterWalk); } // Above water return(ZLiquidStatus.AboveWater); }
public override void UpdateUnderwaterState(Map m, float x, float y, float z) { LiquidData liquid_status; ZLiquidStatus res = m.getLiquidStatus(GetPhaseShift(), x, y, z, MapConst.MapAllLiquidTypes, out liquid_status); if (res == 0) { m_MirrorTimerFlags &= ~(PlayerUnderwaterState.InWater | PlayerUnderwaterState.InLava | PlayerUnderwaterState.InSlime | PlayerUnderwaterState.InDarkWater); if (_lastLiquid != null && _lastLiquid.SpellID != 0) { RemoveAurasDueToSpell(_lastLiquid.SpellID); } _lastLiquid = null; return; } uint liqEntry = liquid_status.entry; if (liqEntry != 0) { LiquidTypeRecord liquid = CliDB.LiquidTypeStorage.LookupByKey(liqEntry); if (_lastLiquid != null && _lastLiquid.SpellID != 0 && _lastLiquid != liquid) { RemoveAurasDueToSpell(_lastLiquid.SpellID); } if (liquid != null && liquid.SpellID != 0) { if (res.HasAnyFlag(ZLiquidStatus.UnderWater | ZLiquidStatus.InWater)) { if (!HasAura(liquid.SpellID)) { CastSpell(this, liquid.SpellID, true); } } else { RemoveAurasDueToSpell(liquid.SpellID); } } _lastLiquid = liquid; } else if (_lastLiquid != null && _lastLiquid.SpellID != 0) { RemoveAurasDueToSpell(_lastLiquid.SpellID); _lastLiquid = null; } // All liquids type - check under water position if (liquid_status.type_flags.HasAnyFlag <uint>(MapConst.MapLiquidTypeWater | MapConst.MapLiquidTypeOcean | MapConst.MapLiquidTypeMagma | MapConst.MapLiquidTypeSlime)) { if (res.HasAnyFlag(ZLiquidStatus.UnderWater)) { m_MirrorTimerFlags |= PlayerUnderwaterState.InWater; } else { m_MirrorTimerFlags &= ~PlayerUnderwaterState.InWater; } } // Allow travel in dark water on taxi or transport if (liquid_status.type_flags.HasAnyFlag <uint>(MapConst.MapLiquidTypeDarkWater) && !IsInFlight() && GetTransport() == null) { m_MirrorTimerFlags |= PlayerUnderwaterState.InDarkWater; } else { m_MirrorTimerFlags &= ~PlayerUnderwaterState.InDarkWater; } // in lava check, anywhere in lava level if (liquid_status.type_flags.HasAnyFlag <uint>(MapConst.MapLiquidTypeMagma)) { if (res.HasAnyFlag(ZLiquidStatus.UnderWater | ZLiquidStatus.InWater | ZLiquidStatus.WaterWalk)) { m_MirrorTimerFlags |= PlayerUnderwaterState.InLava; } else { m_MirrorTimerFlags &= ~PlayerUnderwaterState.InLava; } } // in slime check, anywhere in slime level if (liquid_status.type_flags.HasAnyFlag <uint>(MapConst.MapLiquidTypeSlime)) { if (res.HasAnyFlag(ZLiquidStatus.UnderWater | ZLiquidStatus.InWater | ZLiquidStatus.WaterWalk)) { m_MirrorTimerFlags |= PlayerUnderwaterState.InSlime; } else { m_MirrorTimerFlags &= ~PlayerUnderwaterState.InSlime; } } }