From 84fdaef291b4ae7d547694feeb94f4fd2bffd013 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Sun, 28 Jan 2018 19:37:36 -0500 Subject: [PATCH] Core/Spells: Allow skipping automatic removal of auras from spell_area when condition is no longer met (mostly used for cosmetic cutscenes after quest completion) --- .../Framework/Constants/Spells/SpellConst.cs | 6 + Source/Game/DataStorage/DB2Manager.cs | 130 +++++++++++------- Source/Game/Entities/Player/Player.Quest.cs | 4 +- Source/Game/Entities/Player/Player.Spells.cs | 4 +- Source/Game/Spells/Auras/Aura.cs | 12 +- Source/Game/Spells/SpellManager.cs | 72 +++++++--- 6 files changed, 151 insertions(+), 77 deletions(-) diff --git a/Source/Framework/Constants/Spells/SpellConst.cs b/Source/Framework/Constants/Spells/SpellConst.cs index 315453b93..1651bab39 100644 --- a/Source/Framework/Constants/Spells/SpellConst.cs +++ b/Source/Framework/Constants/Spells/SpellConst.cs @@ -2425,4 +2425,10 @@ namespace Framework.Constants IncludeGCD = 0x1, // Starts GCD in addition to normal cooldown specified in the packet IncludeEventCooldowns = 0x2 // Starts GCD for spells that should start their cooldown on events, requires SPELL_COOLDOWN_FLAG_INCLUDE_GCD set } + + public enum SpellAreaFlag + { + AutoCast = 0x1, // if has autocast, spell is applied on enter + AutoRemove = 0x2, // if has autoremove, spell is remove automatically inside zone/area (allways removed on leaving area or zone) + } } diff --git a/Source/Game/DataStorage/DB2Manager.cs b/Source/Game/DataStorage/DB2Manager.cs index 5407b9f92..4c37a77eb 100644 --- a/Source/Game/DataStorage/DB2Manager.cs +++ b/Source/Game/DataStorage/DB2Manager.cs @@ -47,6 +47,8 @@ namespace Game.DataStorage foreach (var areaGroupMember in CliDB.AreaGroupMemberStorage.Values) _areaGroupMembers.Add(areaGroupMember.AreaGroupID, areaGroupMember.AreaID); + CliDB.AreaGroupMemberStorage.Clear(); + foreach (ArtifactPowerRecord artifactPower in CliDB.ArtifactPowerStorage.Values) _artifactPowers.Add(artifactPower.ArtifactID, artifactPower); @@ -56,21 +58,29 @@ namespace Game.DataStorage _artifactPowerLinks.Add(artifactPowerLink.ToArtifactPowerID, artifactPowerLink.FromArtifactPowerID); } + CliDB.ArtifactPowerLinkStorage.Clear(); + foreach (ArtifactPowerRankRecord artifactPowerRank in CliDB.ArtifactPowerRankStorage.Values) _artifactPowerRanks[Tuple.Create((uint)artifactPowerRank.ArtifactPowerID, artifactPowerRank.Rank)] = artifactPowerRank; + CliDB.ArtifactPowerRankStorage.Clear(); + foreach (CharacterFacialHairStylesRecord characterFacialStyle in CliDB.CharacterFacialHairStylesStorage.Values) _characterFacialHairStyles.Add(Tuple.Create(characterFacialStyle.RaceID, characterFacialStyle.SexID, (uint)characterFacialStyle.VariationID)); + CliDB.CharacterFacialHairStylesStorage.Clear(); + CharBaseSectionVariation[] sectionToBase = new CharBaseSectionVariation[(int)CharSectionType.Max]; foreach (CharBaseSectionRecord charBaseSection in CliDB.CharBaseSectionStorage.Values) { Contract.Assert(charBaseSection.ResolutionVariation < (byte)CharSectionType.Max, $"SECTION_TYPE_MAX ({(byte)CharSectionType.Max}) must be equal to or greater than {charBaseSection.ResolutionVariation + 1}"); Contract.Assert(charBaseSection.Variation < CharBaseSectionVariation.Max, $"CharBaseSectionVariation.Max {(byte)CharBaseSectionVariation.Max} must be equal to or greater than {charBaseSection.Variation + 1}"); - sectionToBase[charBaseSection.ResolutionVariation] = (CharBaseSectionVariation)charBaseSection.Variation; + sectionToBase[charBaseSection.ResolutionVariation] = charBaseSection.Variation; } + CliDB.CharBaseSectionStorage.Clear(); + MultiMap, Tuple> addedSections = new MultiMap, Tuple>(); foreach (CharSectionsRecord charSection in CliDB.CharSectionsStorage.Values) { @@ -85,6 +95,8 @@ namespace Game.DataStorage _charSections.Add(sectionKey, charSection); } + CliDB.CharSectionsStorage.Clear(); + foreach (var outfit in CliDB.CharStartOutfitStorage.Values) _charStartOutfits[(uint)(outfit.RaceID | (outfit.ClassID << 8) | (outfit.GenderID << 16))] = outfit; @@ -92,6 +104,8 @@ namespace Game.DataStorage foreach (var chrClasses in CliDB.ChrClassesXPowerTypesStorage.Values) powers.Add(chrClasses); + CliDB.ChrClassesXPowerTypesStorage.Clear(); + powers.Sort(new ChrClassesXPowerTypesRecordComparer()); foreach (var power in powers) { @@ -129,12 +143,16 @@ namespace Game.DataStorage _curvePoints.Add(curvePoint.CurveID, curvePoint); } + CliDB.CurvePointStorage.Clear(); + foreach (var key in _curvePoints.Keys.ToList()) _curvePoints[key] = _curvePoints[key].OrderBy(point => point.Index).ToList(); foreach (EmotesTextSoundRecord emoteTextSound in CliDB.EmotesTextSoundStorage.Values) _emoteTextSounds[Tuple.Create((uint)emoteTextSound.EmotesTextId, emoteTextSound.RaceId, emoteTextSound.SexId, emoteTextSound.ClassId)] = emoteTextSound; + CliDB.EmotesTextSoundStorage.Clear(); + foreach (FactionRecord faction in CliDB.FactionStorage.Values) if (faction.ParentFactionID != 0) _factionTeams.Add(faction.ParentFactionID, faction.Id); @@ -152,18 +170,28 @@ namespace Game.DataStorage foreach (HeirloomRecord heirloom in CliDB.HeirloomStorage.Values) _heirlooms[heirloom.ItemID] = heirloom; + CliDB.HeirloomStorage.Clear(); + foreach (GlyphBindableSpellRecord glyphBindableSpell in CliDB.GlyphBindableSpellStorage.Values) _glyphBindableSpells.Add(glyphBindableSpell.GlyphPropertiesID, glyphBindableSpell.SpellID); + CliDB.GlyphBindableSpellStorage.Clear(); + foreach (GlyphRequiredSpecRecord glyphRequiredSpec in CliDB.GlyphRequiredSpecStorage.Values) _glyphRequiredSpecs.Add(glyphRequiredSpec.GlyphPropertiesID, glyphRequiredSpec.ChrSpecializationID); + CliDB.GlyphRequiredSpecStorage.Clear(); + foreach (var bonus in CliDB.ItemBonusStorage.Values) _itemBonusLists.Add(bonus.BonusListID, bonus); + CliDB.ItemBonusStorage.Clear(); + foreach (ItemBonusListLevelDeltaRecord itemBonusListLevelDelta in CliDB.ItemBonusListLevelDeltaStorage.Values) _itemLevelDeltaToBonusListContainer[itemBonusListLevelDelta.Delta] = itemBonusListLevelDelta.Id; + CliDB.ItemBonusListLevelDeltaStorage.Clear(); + foreach (var key in CliDB.ItemBonusTreeNodeStorage.Keys) { ItemBonusTreeNodeRecord bonusTreeNode = CliDB.ItemBonusTreeNodeStorage[key]; @@ -175,12 +203,16 @@ namespace Game.DataStorage } } + CliDB.ItemBonusTreeNodeStorage.Clear(); + foreach (ItemChildEquipmentRecord itemChildEquipment in CliDB.ItemChildEquipmentStorage.Values) { //ASSERT(_itemChildEquipment.find(itemChildEquipment.ItemID) == _itemChildEquipment.end(), "Item must have max 1 child item."); _itemChildEquipment[itemChildEquipment.ItemID] = itemChildEquipment; } + CliDB.ItemChildEquipmentStorage.Clear(); + foreach (ItemClassRecord itemClass in CliDB.ItemClassStorage.Values) { //ASSERT(itemClass->OldEnumValue < _itemClassByOldEnum.size()); @@ -188,12 +220,18 @@ namespace Game.DataStorage _itemClassByOldEnum[itemClass.OldEnumValue] = itemClass; } + CliDB.ItemClassStorage.Clear(); + foreach (ItemCurrencyCostRecord itemCurrencyCost in CliDB.ItemCurrencyCostStorage.Values) _itemsWithCurrencyCost.Add(itemCurrencyCost.ItemId); + CliDB.ItemCurrencyCostStorage.Clear(); + foreach (ItemLevelSelectorQualityRecord itemLevelSelectorQuality in CliDB.ItemLevelSelectorQualityStorage.Values) _itemLevelQualitySelectorQualities.Add(itemLevelSelectorQuality.ItemLevelSelectorQualitySetID, itemLevelSelectorQuality); - + + CliDB.ItemLevelSelectorQualityStorage.Clear(); + foreach (var appearanceMod in CliDB.ItemModifiedAppearanceStorage.Values) { //ASSERT(appearanceMod.ItemID <= 0xFFFFFF); @@ -203,12 +241,18 @@ namespace Game.DataStorage foreach (ItemSetSpellRecord itemSetSpell in CliDB.ItemSetSpellStorage.Values) _itemSetSpells.Add(itemSetSpell.ItemSetID, itemSetSpell); + CliDB.ItemSetSpellStorage.Clear(); + foreach (var itemSpecOverride in CliDB.ItemSpecOverrideStorage.Values) _itemSpecOverrides.Add(itemSpecOverride.ItemID, itemSpecOverride); + CliDB.ItemSpecOverrideStorage.Clear(); + foreach (var itemBonusTreeAssignment in CliDB.ItemXBonusTreeStorage.Values) _itemToBonusTree.Add(itemBonusTreeAssignment.ItemID, itemBonusTreeAssignment.BonusTreeID); + CliDB.ItemXBonusTreeStorage.Clear(); + foreach (MapDifficultyRecord entry in CliDB.MapDifficultyStorage.Values) { if (!_mapDifficulties.ContainsKey(entry.MapID)) @@ -218,18 +262,24 @@ namespace Game.DataStorage } _mapDifficulties[0][0] = _mapDifficulties[1][0]; // map 0 is missing from MapDifficulty.dbc so we cheat a bit + CliDB.MapDifficultyStorage.Clear(); + foreach (var mount in CliDB.MountStorage.Values) _mountsBySpellId[mount.SpellId] = mount; foreach (MountTypeXCapabilityRecord mountTypeCapability in CliDB.MountTypeXCapabilityStorage.Values) _mountCapabilitiesByType.Add(mountTypeCapability.MountTypeID, mountTypeCapability); + CliDB.MountTypeXCapabilityStorage.Clear(); + foreach (var key in _mountCapabilitiesByType.Keys) _mountCapabilitiesByType[key].Sort(new MountTypeXCapabilityRecordComparer()); foreach (MountXDisplayRecord mountDisplay in CliDB.MountXDisplayStorage.Values) _mountDisplays.Add(mountDisplay.MountID, mountDisplay); + CliDB.MountXDisplayStorage.Clear(); + foreach (var entry in CliDB.NameGenStorage.Values) { if (!_nameGenData.ContainsKey(entry.Race)) @@ -242,6 +292,8 @@ namespace Game.DataStorage _nameGenData[entry.Race][entry.Sex].Add(entry); } + CliDB.NameGenStorage.Clear(); + foreach (var namesProfanity in CliDB.NamesProfanityStorage.Values) { Contract.Assert(namesProfanity.Language < (int)LocaleConstant.Total || namesProfanity.Language == -1); @@ -257,9 +309,13 @@ namespace Game.DataStorage } } + CliDB.NamesProfanityStorage.Clear(); + foreach (var namesReserved in CliDB.NamesReservedStorage.Values) _nameValidators[(int)LocaleConstant.Total].Add(new Regex(namesReserved.Name, RegexOptions.IgnoreCase | RegexOptions.Compiled)); + CliDB.NamesReservedStorage.Clear(); + foreach (var namesReserved in CliDB.NamesReservedLocaleStorage.Values) { Contract.Assert(!Convert.ToBoolean(namesReserved.LocaleMask & ~((1 << (int)LocaleConstant.Total) - 1))); @@ -272,6 +328,7 @@ namespace Game.DataStorage _nameValidators[i].Add(new Regex(namesReserved.Name, RegexOptions.IgnoreCase | RegexOptions.Compiled)); } } + CliDB.NamesReservedLocaleStorage.Clear(); foreach (var group in CliDB.PhaseXPhaseGroupStorage.Values) { @@ -279,6 +336,7 @@ namespace Game.DataStorage if (phase != null) _phasesByGroup.Add(group.PhaseGroupID, phase.Id); } + CliDB.PhaseXPhaseGroupStorage.Clear(); foreach (PowerTypeRecord powerType in CliDB.PowerTypeStorage.Values) { @@ -290,6 +348,8 @@ namespace Game.DataStorage foreach (PvpRewardRecord pvpReward in CliDB.PvpRewardStorage.Values) _pvpRewardPack[Tuple.Create(pvpReward.Prestige, pvpReward.HonorLevel)] = pvpReward.RewardPackID; + CliDB.PvpRewardStorage.Clear(); + foreach (QuestPackageItemRecord questPackageItem in CliDB.QuestPackageItemStorage.Values) { if (!_questPackages.ContainsKey(questPackageItem.QuestPackageID)) @@ -301,12 +361,18 @@ namespace Game.DataStorage _questPackages[questPackageItem.QuestPackageID].Item2.Add(questPackageItem); } + CliDB.QuestPackageItemStorage.Clear(); + foreach (RewardPackXItemRecord rewardPackXItem in CliDB.RewardPackXItemStorage.Values) _rewardPackItems.Add(rewardPackXItem.RewardPackID, rewardPackXItem); + CliDB.RewardPackXItemStorage.Clear(); + foreach (RulesetItemUpgradeRecord rulesetItemUpgrade in CliDB.RulesetItemUpgradeStorage.Values) _rulesetItemUpgrade[rulesetItemUpgrade.ItemID] = rulesetItemUpgrade.ItemUpgradeID; + CliDB.RulesetItemUpgradeStorage.Clear(); + foreach (SkillRaceClassInfoRecord entry in CliDB.SkillRaceClassInfoStorage.Values) { if (CliDB.SkillLineStorage.ContainsKey(entry.SkillID)) @@ -316,10 +382,12 @@ namespace Game.DataStorage foreach (var specSpells in CliDB.SpecializationSpellsStorage.Values) _specializationSpellsBySpec.Add(specSpells.SpecID, specSpells); + CliDB.SpecializationSpellsStorage.Clear(); + foreach (SpellClassOptionsRecord classOption in CliDB.SpellClassOptionsStorage.Values) _spellFamilyNames.Add(classOption.SpellClassSet); - foreach (var power in CliDB.SpellPowerStorage.Values) + foreach (SpellPowerRecord power in CliDB.SpellPowerStorage.Values) { SpellPowerDifficultyRecord powerDifficulty = CliDB.SpellPowerDifficultyStorage.LookupByKey(power.Id); if (powerDifficulty != null) @@ -341,9 +409,13 @@ namespace Game.DataStorage } } + CliDB.SpellPowerStorage.Clear(); + foreach (SpellProcsPerMinuteModRecord ppmMod in CliDB.SpellProcsPerMinuteModStorage.Values) _spellProcsPerMinuteMods.Add(ppmMod.SpellProcsPerMinuteID, ppmMod); + CliDB.SpellProcsPerMinuteModStorage.Clear(); + for (var i = 0; i < (int)Class.Max; ++i) { _talentsByPosition[i] = new List[PlayerConst.MaxTalentTiers][]; @@ -355,6 +427,7 @@ namespace Game.DataStorage _talentsByPosition[i][x][c] = new List(); } } + foreach (TalentRecord talentInfo in CliDB.TalentStorage.Values) { //ASSERT(talentInfo.ClassID < MAX_CLASSES); @@ -366,6 +439,8 @@ namespace Game.DataStorage foreach (ToyRecord toy in CliDB.ToyStorage.Values) _toys.Add(toy.ItemID); + CliDB.ToyStorage.Clear(); + foreach (TransmogSetItemRecord transmogSetItem in CliDB.TransmogSetItemStorage.Values) { TransmogSetRecord set = CliDB.TransmogSetStorage.LookupByKey(transmogSetItem.TransmogSetID); @@ -376,56 +451,17 @@ namespace Game.DataStorage _transmogSetItemsByTransmogSet.Add(transmogSetItem.TransmogSetID, transmogSetItem); } + CliDB.TransmogSetItemStorage.Clear(); + foreach (WMOAreaTableRecord entry in CliDB.WMOAreaTableStorage.Values) _wmoAreaTableLookup[Tuple.Create(entry.WMOID, entry.NameSet, entry.WMOGroupID)] = entry; + CliDB.WMOAreaTableStorage.Clear(); + foreach (WorldMapAreaRecord worldMapArea in CliDB.WorldMapAreaStorage.Values) _worldMapAreaByAreaID[worldMapArea.AreaID] = worldMapArea; - ClearNotUsedTables(); - } - - void ClearNotUsedTables() - { - CliDB.AreaGroupMemberStorage = null; - CliDB.ArtifactPowerLinkStorage = null; - CliDB.ArtifactPowerRankStorage = null; - CliDB.CharSectionsStorage = null; - CliDB.ChrClassesXPowerTypesStorage = null; - CliDB.CurvePointStorage = null; - CliDB.EmotesTextSoundStorage = null; - CliDB.GlyphBindableSpellStorage = null; - CliDB.GlyphRequiredSpecStorage = null; - CliDB.HeirloomStorage = null; - CliDB.ItemBonusStorage = null; - CliDB.ItemBonusListLevelDeltaStorage = null; - CliDB.ItemBonusTreeNodeStorage = null; - CliDB.ItemClassStorage = null; - CliDB.ItemChildEquipmentStorage = null; - CliDB.ItemCurrencyCostStorage = null; - CliDB.ItemSetSpellStorage = null; - CliDB.ItemSpecOverrideStorage = null; - CliDB.ItemXBonusTreeStorage = null; - CliDB.MapDifficultyStorage = null; - CliDB.MountTypeXCapabilityStorage = null; - CliDB.MountXDisplayStorage = null; - CliDB.NameGenStorage = null; - CliDB.NamesProfanityStorage = null; - CliDB.NamesReservedStorage = null; - CliDB.NamesReservedLocaleStorage = null; - CliDB.PhaseXPhaseGroupStorage = null; - CliDB.PowerTypeStorage = null; - CliDB.PvpRewardStorage = null; - CliDB.QuestPackageItemStorage = null; - CliDB.RewardPackXItemStorage = null; - CliDB.RulesetItemUpgradeStorage = null; - CliDB.SpecializationSpellsStorage = null; - CliDB.SpellPowerDifficultyStorage = null; - CliDB.SpellPowerStorage = null; - CliDB.SpellProcsPerMinuteModStorage = null; - CliDB.ToyStorage = null; - CliDB.WMOAreaTableStorage = null; - CliDB.WorldMapAreaStorage = null; + CliDB.WorldMapAreaStorage.Clear(); } public IDB2Storage GetStorage(uint type) diff --git a/Source/Game/Entities/Player/Player.Quest.cs b/Source/Game/Entities/Player/Player.Quest.cs index 2d0687a82..00b5752e4 100644 --- a/Source/Game/Entities/Player/Player.Quest.cs +++ b/Source/Game/Entities/Player/Player.Quest.cs @@ -1802,9 +1802,9 @@ namespace Game.Entities { foreach (var spell in saBounds) { - if (!spell.IsFitToRequirements(this, zone, area)) + if (spell.flags.HasAnyFlag(SpellAreaFlag.AutoRemove) && !spell.IsFitToRequirements(this, zone, area)) RemoveAurasDueToSpell(spell.spellId); - else if (spell.autocast) + else if (spell.flags.HasAnyFlag(SpellAreaFlag.AutoCast)) if (!HasAura(spell.spellId)) CastSpell(this, spell.spellId, true); } diff --git a/Source/Game/Entities/Player/Player.Spells.cs b/Source/Game/Entities/Player/Player.Spells.cs index a8f54d238..e58f5051d 100644 --- a/Source/Game/Entities/Player/Player.Spells.cs +++ b/Source/Game/Entities/Player/Player.Spells.cs @@ -1765,7 +1765,7 @@ namespace Game.Entities // Some spells applied at enter into zone (with subzones), aura removed in UpdateAreaDependentAuras that called always at zone.area update var saBounds = Global.SpellMgr.GetSpellAreaForAreaMapBounds(newZone); foreach (var spell in saBounds) - if (spell.autocast && spell.IsFitToRequirements(this, newZone, 0)) + if (spell.flags.HasAnyFlag(SpellAreaFlag.AutoCast) && spell.IsFitToRequirements(this, newZone, 0)) if (!HasAura(spell.spellId)) CastSpell(this, spell.spellId, true); } @@ -1783,7 +1783,7 @@ namespace Game.Entities // some auras applied at subzone enter var saBounds = Global.SpellMgr.GetSpellAreaForAreaMapBounds(newArea); foreach (var spell in saBounds) - if (spell.autocast && spell.IsFitToRequirements(this, m_zoneUpdateId, newArea)) + if (spell.flags.HasAnyFlag(SpellAreaFlag.AutoCast) && spell.IsFitToRequirements(this, m_zoneUpdateId, newArea)) if (!HasAura(spell.spellId)) CastSpell(this, spell.spellId, true); } diff --git a/Source/Game/Spells/Auras/Aura.cs b/Source/Game/Spells/Auras/Aura.cs index df6bc6d3a..7a0907d80 100644 --- a/Source/Game/Spells/Auras/Aura.cs +++ b/Source/Game/Spells/Auras/Aura.cs @@ -1132,16 +1132,16 @@ namespace Game.Spells uint zone, area; target.GetZoneAndAreaId(out zone, out area); - foreach (var bound in saBounds) + foreach (var spellArea in saBounds) { // some auras remove at aura remove - if (!bound.IsFitToRequirements((Player)target, zone, area)) - target.RemoveAurasDueToSpell(bound.spellId); + if (spellArea.flags.HasAnyFlag(SpellAreaFlag.AutoRemove) && !spellArea.IsFitToRequirements((Player)target, zone, area)) + target.RemoveAurasDueToSpell(spellArea.spellId); // some auras applied at aura apply - else if (bound.autocast) + else if (spellArea.flags.HasAnyFlag(SpellAreaFlag.AutoCast)) { - if (!target.HasAura(bound.spellId)) - target.CastSpell(target, bound.spellId, true); + if (!target.HasAura(spellArea.spellId)) + target.CastSpell(target, spellArea.spellId, true); } } } diff --git a/Source/Game/Spells/SpellManager.cs b/Source/Game/Spells/SpellManager.cs index cf5f16762..2ff02a0cc 100644 --- a/Source/Game/Spells/SpellManager.cs +++ b/Source/Game/Spells/SpellManager.cs @@ -1742,8 +1742,8 @@ namespace Game.Entities mSpellAreaForQuestEndMap.Clear(); mSpellAreaForAuraMap.Clear(); - // 0 1 2 3 4 5 6 7 8 9 - SQLResult result = DB.World.Query("SELECT spell, area, quest_start, quest_start_status, quest_end_status, quest_end, aura_spell, racemask, gender, autocast FROM spell_area"); + // 0 1 2 3 4 5 6 7 8 9 + SQLResult result = DB.World.Query("SELECT spell, area, quest_start, quest_start_status, quest_end_status, quest_end, aura_spell, racemask, gender, flags FROM spell_area"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 spell area requirements. DB table `spell_area` is empty."); @@ -1766,12 +1766,12 @@ namespace Game.Entities spellArea.auraSpell = result.Read(6); spellArea.raceMask = result.Read(7); spellArea.gender = (Gender)result.Read(8); - spellArea.autocast = result.Read(9); + spellArea.flags = (SpellAreaFlag)result.Read(9); SpellInfo spellInfo = GetSpellInfo(spell); if (spellInfo != null) { - if (spellArea.autocast) + if (spellArea.flags.HasAnyFlag(SpellAreaFlag.AutoCast)) spellInfo.Attributes |= SpellAttr0.CantCancel; } else @@ -1847,13 +1847,13 @@ namespace Game.Entities } // not allow autocast chains by auraSpell field (but allow use as alternative if not present) - if (spellArea.autocast && spellArea.auraSpell > 0) + if (spellArea.flags.HasAnyFlag(SpellAreaFlag.AutoCast) && spellArea.auraSpell > 0) { bool chain = false; var saBound = GetSpellAreaForAuraMapBounds(spellArea.spellId); foreach (var bound in saBound) { - if (bound.autocast && bound.auraSpell > 0) + if (bound.flags.HasAnyFlag(SpellAreaFlag.AutoCast) && bound.auraSpell > 0) { chain = true; break; @@ -1869,7 +1869,7 @@ namespace Game.Entities var saBound2 = GetSpellAreaMapBounds((uint)spellArea.auraSpell); foreach (var bound in saBound2) { - if (bound.autocast && bound.auraSpell > 0) + if (bound.flags.HasAnyFlag(SpellAreaFlag.AutoCast) && bound.auraSpell > 0) { chain = true; break; @@ -1947,11 +1947,6 @@ namespace Game.Entities if (!effectsBySpell.ContainsKey(effect.SpellID)) effectsBySpell[effect.SpellID] = new Dictionary(); - if(effect.DifficultyID > (int)Difficulty.Max) - { - - } - if (!effectsBySpell[effect.SpellID].ContainsKey(effect.DifficultyID)) effectsBySpell[effect.SpellID][effect.DifficultyID] = new SpellEffectRecord[SpellConst.MaxEffects]; @@ -1965,54 +1960,89 @@ namespace Game.Entities if (auraOptions.DifficultyID == 0) // TODO: implement loadData[auraOptions.SpellID].AuraOptions = auraOptions; + CliDB.SpellAuraOptionsStorage.Clear(); + foreach (SpellAuraRestrictionsRecord auraRestrictions in CliDB.SpellAuraRestrictionsStorage.Values) + { if (auraRestrictions.DifficultyID == 0) // TODO: implement loadData[auraRestrictions.SpellID].AuraRestrictions = auraRestrictions; + } + CliDB.SpellAuraRestrictionsStorage.Clear(); foreach (SpellCastingRequirementsRecord castingRequirements in CliDB.SpellCastingRequirementsStorage.Values) loadData[castingRequirements.SpellID].CastingRequirements = castingRequirements; + CliDB.SpellCastingRequirementsStorage.Clear(); + foreach (SpellCategoriesRecord categories in CliDB.SpellCategoriesStorage.Values) + { if (categories.DifficultyID == 0) // TODO: implement loadData[categories.SpellID].Categories = categories; + } + CliDB.SpellCategoriesStorage.Clear(); foreach (SpellClassOptionsRecord classOptions in CliDB.SpellClassOptionsStorage.Values) loadData[classOptions.SpellID].ClassOptions = classOptions; + CliDB.SpellClassOptionsStorage.Clear(); + foreach (SpellCooldownsRecord cooldowns in CliDB.SpellCooldownsStorage.Values) + { if (cooldowns.DifficultyID == 0) // TODO: implement loadData[cooldowns.SpellID].Cooldowns = cooldowns; + } + CliDB.SpellCooldownsStorage.Clear(); foreach (SpellEffectScalingRecord spellEffectScaling in CliDB.SpellEffectScalingStorage.Values) spellEffectScallingByEffectId[spellEffectScaling.SpellEffectID] = spellEffectScaling; + CliDB.SpellEffectScalingStorage.Clear(); + foreach (SpellEquippedItemsRecord equippedItems in CliDB.SpellEquippedItemsStorage.Values) loadData[equippedItems.SpellID].EquippedItems = equippedItems; + CliDB.SpellEquippedItemsStorage.Clear(); + foreach (SpellInterruptsRecord interrupts in CliDB.SpellInterruptsStorage.Values) + { if (interrupts.DifficultyID == 0) // TODO: implement loadData[interrupts.SpellID].Interrupts = interrupts; + } + CliDB.SpellInterruptsStorage.Clear(); foreach (SpellLevelsRecord levels in CliDB.SpellLevelsStorage.Values) + { if (levels.DifficultyID == 0) // TODO: implement loadData[levels.SpellID].Levels = levels; + } foreach (SpellReagentsRecord reagents in CliDB.SpellReagentsStorage.Values) loadData[reagents.SpellID].Reagents = reagents; + CliDB.SpellReagentsStorage.Clear(); + foreach (SpellScalingRecord scaling in CliDB.SpellScalingStorage.Values) loadData[scaling.SpellID].Scaling = scaling; + CliDB.SpellScalingStorage.Clear(); + foreach (SpellShapeshiftRecord shapeshift in CliDB.SpellShapeshiftStorage.Values) loadData[shapeshift.SpellID].Shapeshift = shapeshift; + CliDB.SpellShapeshiftStorage.Clear(); + foreach (SpellTargetRestrictionsRecord targetRestrictions in CliDB.SpellTargetRestrictionsStorage.Values) + { if (targetRestrictions.DifficultyID == 0) // TODO: implement loadData[targetRestrictions.SpellID].TargetRestrictions = targetRestrictions; + } + CliDB.SpellTargetRestrictionsStorage.Clear(); foreach (SpellTotemsRecord totems in CliDB.SpellTotemsStorage.Values) loadData[totems.SpellID].Totems = totems; + CliDB.SpellTotemsStorage.Clear(); + foreach (var visual in CliDB.SpellXSpellVisualStorage.Values) { if (!visualsBySpell.ContainsKey(visual.SpellID)) @@ -2028,6 +2058,8 @@ namespace Game.Entities mSpellInfoMap[spellEntry.Id] = new SpellInfo(loadData[spellEntry.Id], effectsBySpell.LookupByKey(spellEntry.Id), visualsBySpell.LookupByKey(spellEntry.Id), spellEffectScallingByEffectId); } + CliDB.SpellStorage.Clear(); + Log.outInfo(LogFilter.ServerLoading, "Loaded SpellInfo store in {0} ms", Time.GetMSTimeDiffToNow(oldMSTime)); } @@ -3161,15 +3193,15 @@ namespace Game.Entities public class SpellArea { public uint spellId; - public uint areaId; // zone/subzone/or 0 is not limited to zone - public uint questStart; // quest start (quest must be active or rewarded for spell apply) - public uint questEnd; // quest end (quest must not be rewarded for spell apply) + public uint areaId; // zone/subzone/or 0 is not limited to zone + public uint questStart; // quest start (quest must be active or rewarded for spell apply) + public uint questEnd; // quest end (quest must not be rewarded for spell apply) public int auraSpell; // spell aura must be applied for spell apply)if possitive) and it must not be applied in other case - public uint raceMask; // can be applied only to races - public Gender gender; // can be applied only to gender - public uint questStartStatus; // QuestStatus that quest_start must have in order to keep the spell - public uint questEndStatus; // QuestStatus that the quest_end must have in order to keep the spell (if the quest_end's status is different than this, the spell will be dropped) - public bool autocast; // if true then auto applied at area enter, in other case just allowed to cast + public uint raceMask; // can be applied only to races + public Gender gender; // can be applied only to gender + public uint questStartStatus; // QuestStatus that quest_start must have in order to keep the spell + public uint questEndStatus; // QuestStatus that the quest_end must have in order to keep the spell (if the quest_end's status is different than this, the spell will be dropped) + public SpellAreaFlag flags; // if SPELL_AREA_FLAG_AUTOCAST then auto applied at area enter, in other case just allowed to cast || if SPELL_AREA_FLAG_AUTOREMOVE then auto removed inside area (will allways be removed on leaved even without flag) // helpers public bool IsFitToRequirements(Player player, uint newZone, uint newArea)