Ported .Net Core commits:
hondacrx: - Initial commit: Switch to .Net Core 2.0 - Fix build and removed not needed files Fabi: - Updated solution platforms. - Changed folder structure. - Change library target framework to netstandard2.0. - Updated solution platforms again... - Removed windows specific kernel32 function usage (Ctrl-C handler).
This commit is contained in:
@@ -0,0 +1,578 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Text;
|
||||
|
||||
namespace Game.Conditions
|
||||
{
|
||||
public class Condition
|
||||
{
|
||||
public Condition()
|
||||
{
|
||||
SourceType = ConditionSourceType.None;
|
||||
ConditionType = ConditionTypes.None;
|
||||
}
|
||||
|
||||
public bool Meets(ConditionSourceInfo sourceInfo)
|
||||
{
|
||||
Contract.Assert(ConditionTarget < SharedConst.MaxConditionTargets);
|
||||
WorldObject obj = sourceInfo.mConditionTargets[ConditionTarget];
|
||||
// object not present, return false
|
||||
if (obj == null)
|
||||
{
|
||||
Log.outDebug(LogFilter.Condition, "Condition object not found for condition (Entry: {0} Type: {1} Group: {2})", SourceEntry, SourceType, SourceGroup);
|
||||
return false;
|
||||
}
|
||||
bool condMeets = false;
|
||||
|
||||
Player player = obj.ToPlayer();
|
||||
Unit unit = obj.ToUnit();
|
||||
|
||||
switch (ConditionType)
|
||||
{
|
||||
case ConditionTypes.None:
|
||||
condMeets = true; // empty condition, always met
|
||||
break;
|
||||
case ConditionTypes.Aura:
|
||||
if (unit != null)
|
||||
condMeets = unit.HasAuraEffect(ConditionValue1, (byte)ConditionValue2);
|
||||
break;
|
||||
case ConditionTypes.Item:
|
||||
if (player != null)
|
||||
{
|
||||
// don't allow 0 items (it's checked during table load)
|
||||
Contract.Assert(ConditionValue2 != 0);
|
||||
bool checkBank = ConditionValue3 != 0 ? true : false;
|
||||
condMeets = player.HasItemCount(ConditionValue1, ConditionValue2, checkBank);
|
||||
}
|
||||
break;
|
||||
case ConditionTypes.ItemEquipped:
|
||||
if (player != null)
|
||||
condMeets = player.HasItemOrGemWithIdEquipped(ConditionValue1, 1);
|
||||
break;
|
||||
case ConditionTypes.Zoneid:
|
||||
condMeets = obj.GetZoneId() == ConditionValue1;
|
||||
break;
|
||||
case ConditionTypes.ReputationRank:
|
||||
if (player != null)
|
||||
{
|
||||
var faction = CliDB.FactionStorage.LookupByKey(ConditionValue1);
|
||||
if (faction != null)
|
||||
condMeets = Convert.ToBoolean(ConditionValue2 & (1 << (int)player.GetReputationMgr().GetRank(faction)));
|
||||
}
|
||||
break;
|
||||
case ConditionTypes.Achievement:
|
||||
if (player != null)
|
||||
condMeets = player.HasAchieved(ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.Team:
|
||||
if (player != null)
|
||||
condMeets = (uint)player.GetTeam() == ConditionValue1;
|
||||
break;
|
||||
case ConditionTypes.Class:
|
||||
if (unit != null)
|
||||
condMeets = Convert.ToBoolean(unit.getClassMask() & ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.Race:
|
||||
if (unit != null)
|
||||
condMeets = Convert.ToBoolean(unit.getRaceMask() & ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.Gender:
|
||||
if (player != null)
|
||||
condMeets = player.GetGender() == (Gender)ConditionValue1;
|
||||
break;
|
||||
case ConditionTypes.Skill:
|
||||
if (player != null)
|
||||
condMeets = player.HasSkill((SkillType)ConditionValue1) && player.GetBaseSkillValue((SkillType)ConditionValue1) >= ConditionValue2;
|
||||
break;
|
||||
case ConditionTypes.QuestRewarded:
|
||||
if (player != null)
|
||||
condMeets = player.GetQuestRewardStatus(ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.QuestTaken:
|
||||
if (player != null)
|
||||
{
|
||||
QuestStatus status = player.GetQuestStatus(ConditionValue1);
|
||||
condMeets = (status == QuestStatus.Incomplete);
|
||||
}
|
||||
break;
|
||||
case ConditionTypes.QuestComplete:
|
||||
if (player != null)
|
||||
{
|
||||
QuestStatus status = player.GetQuestStatus(ConditionValue1);
|
||||
condMeets = (status == QuestStatus.Complete && !player.GetQuestRewardStatus(ConditionValue1));
|
||||
}
|
||||
break;
|
||||
case ConditionTypes.QuestNone:
|
||||
if (player != null)
|
||||
{
|
||||
QuestStatus status = player.GetQuestStatus(ConditionValue1);
|
||||
condMeets = (status == QuestStatus.None);
|
||||
}
|
||||
break;
|
||||
case ConditionTypes.ActiveEvent:
|
||||
condMeets = Global.GameEventMgr.IsActiveEvent((ushort)ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.InstanceInfo:
|
||||
{
|
||||
var map = obj.GetMap();
|
||||
if (map.IsDungeon())
|
||||
{
|
||||
InstanceScript instance = ((InstanceMap)map).GetInstanceScript();
|
||||
if (instance != null)
|
||||
{
|
||||
switch ((InstanceInfo)ConditionValue3)
|
||||
{
|
||||
case InstanceInfo.Data:
|
||||
condMeets = instance.GetData(ConditionValue1) == ConditionValue2;
|
||||
break;
|
||||
case InstanceInfo.Data64:
|
||||
condMeets = instance.GetData64(ConditionValue1) == ConditionValue2;
|
||||
break;
|
||||
case InstanceInfo.BossState:
|
||||
condMeets = instance.GetBossState(ConditionValue1) == (EncounterState)ConditionValue2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ConditionTypes.Mapid:
|
||||
condMeets = obj.GetMapId() == ConditionValue1;
|
||||
break;
|
||||
case ConditionTypes.Areaid:
|
||||
condMeets = obj.GetAreaId() == ConditionValue1;
|
||||
break;
|
||||
case ConditionTypes.Spell:
|
||||
if (player != null)
|
||||
condMeets = player.HasSpell(ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.Level:
|
||||
if (unit != null)
|
||||
condMeets = MathFunctions.CompareValues((ComparisionType)ConditionValue2, unit.getLevel(), ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.DrunkenState:
|
||||
if (player != null)
|
||||
condMeets = (uint)Player.GetDrunkenstateByValue(player.GetDrunkValue()) >= ConditionValue1;
|
||||
break;
|
||||
case ConditionTypes.NearCreature:
|
||||
condMeets = obj.FindNearestCreature(ConditionValue1, ConditionValue2, ConditionValue3 == 0 ? true : false) != null;
|
||||
break;
|
||||
case ConditionTypes.NearGameobject:
|
||||
condMeets = obj.FindNearestGameObject(ConditionValue1, ConditionValue2) != null;
|
||||
break;
|
||||
case ConditionTypes.ObjectEntryGuid:
|
||||
if ((uint)obj.GetTypeId() == ConditionValue1)
|
||||
{
|
||||
condMeets = ConditionValue2 == 0 || (obj.GetEntry() == ConditionValue2);
|
||||
|
||||
if (ConditionValue3 != 0)
|
||||
{
|
||||
switch (obj.GetTypeId())
|
||||
{
|
||||
case TypeId.Unit:
|
||||
condMeets &= obj.ToCreature().GetSpawnId() == ConditionValue3;
|
||||
break;
|
||||
case TypeId.GameObject:
|
||||
condMeets &= obj.ToGameObject().GetSpawnId() == ConditionValue3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ConditionTypes.TypeMask:
|
||||
condMeets = Convert.ToBoolean((TypeMask)ConditionValue1 & obj.objectTypeMask);
|
||||
break;
|
||||
case ConditionTypes.RelationTo:
|
||||
{
|
||||
WorldObject toObject = sourceInfo.mConditionTargets[ConditionValue1];
|
||||
if (toObject != null)
|
||||
{
|
||||
Unit toUnit = toObject.ToUnit();
|
||||
if (toUnit != null && unit != null)
|
||||
{
|
||||
switch ((RelationType)ConditionValue2)
|
||||
{
|
||||
case RelationType.Self:
|
||||
condMeets = unit == toUnit;
|
||||
break;
|
||||
case RelationType.InParty:
|
||||
condMeets = unit.IsInPartyWith(toUnit);
|
||||
break;
|
||||
case RelationType.InRaidOrParty:
|
||||
condMeets = unit.IsInRaidWith(toUnit);
|
||||
break;
|
||||
case RelationType.OwnedBy:
|
||||
condMeets = unit.GetOwnerGUID() == toUnit.GetGUID();
|
||||
break;
|
||||
case RelationType.PassengerOf:
|
||||
condMeets = unit.IsOnVehicle(toUnit);
|
||||
break;
|
||||
case RelationType.CreatedBy:
|
||||
condMeets = unit.GetCreatorGUID() == toUnit.GetGUID();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ConditionTypes.ReactionTo:
|
||||
{
|
||||
WorldObject toObject = sourceInfo.mConditionTargets[ConditionValue1];
|
||||
if (toObject != null)
|
||||
{
|
||||
Unit toUnit = toObject.ToUnit();
|
||||
if (toUnit != null && unit != null)
|
||||
condMeets = Convert.ToBoolean((1 << (int)unit.GetReactionTo(toUnit)) & ConditionValue2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ConditionTypes.DistanceTo:
|
||||
{
|
||||
WorldObject toObject = sourceInfo.mConditionTargets[ConditionValue1];
|
||||
if (toObject != null)
|
||||
condMeets = MathFunctions.CompareValues((ComparisionType)ConditionValue3, obj.GetDistance(toObject), ConditionValue2);
|
||||
break;
|
||||
}
|
||||
case ConditionTypes.Alive:
|
||||
if (unit != null)
|
||||
condMeets = unit.IsAlive();
|
||||
break;
|
||||
case ConditionTypes.HpVal:
|
||||
if (unit != null)
|
||||
condMeets = MathFunctions.CompareValues((ComparisionType)ConditionValue2, unit.GetHealth(), ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.HpPct:
|
||||
if (unit != null)
|
||||
condMeets = MathFunctions.CompareValues((ComparisionType)ConditionValue2, unit.GetHealthPct(), ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.WorldState:
|
||||
condMeets = (ConditionValue2 == Global.WorldMgr.getWorldState((WorldStates)ConditionValue1));
|
||||
break;
|
||||
case ConditionTypes.PhaseId:
|
||||
condMeets = obj.IsInPhase(ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.Title:
|
||||
if (player != null)
|
||||
condMeets = player.HasTitle(ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.Spawnmask:
|
||||
condMeets = Convert.ToBoolean((1 << (int)obj.GetMap().GetSpawnMode()) & ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.UnitState:
|
||||
if (unit != null)
|
||||
condMeets = unit.HasUnitState((UnitState)ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.CreatureType:
|
||||
{
|
||||
Creature creature = obj.ToCreature();
|
||||
if (creature)
|
||||
condMeets = (uint)creature.GetCreatureTemplate().CreatureType == ConditionValue1;
|
||||
break;
|
||||
}
|
||||
case ConditionTypes.RealmAchievement:
|
||||
{
|
||||
AchievementRecord achievement = CliDB.AchievementStorage.LookupByKey(ConditionValue1);
|
||||
if (achievement != null && Global.AchievementMgr.IsRealmCompleted(achievement))
|
||||
condMeets = true;
|
||||
break;
|
||||
}
|
||||
case ConditionTypes.InWater:
|
||||
if (unit)
|
||||
condMeets = unit.IsInWater();
|
||||
break;
|
||||
case ConditionTypes.TerrainSwap:
|
||||
condMeets = obj.IsInTerrainSwap(ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.StandState:
|
||||
{
|
||||
if (unit)
|
||||
{
|
||||
if (ConditionValue1 == 0)
|
||||
condMeets = (unit.GetStandState() == (UnitStandStateType)ConditionValue2);
|
||||
else if (ConditionValue2 == 0)
|
||||
condMeets = unit.IsStandState();
|
||||
else if (ConditionValue2 == 1)
|
||||
condMeets = unit.IsSitState();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ConditionTypes.DailyQuestDone:
|
||||
{
|
||||
if (player)
|
||||
condMeets = player.IsDailyQuestDone(ConditionValue1);
|
||||
break;
|
||||
}
|
||||
case ConditionTypes.Charmed:
|
||||
{
|
||||
if (unit)
|
||||
condMeets = unit.IsCharmed();
|
||||
break;
|
||||
}
|
||||
case ConditionTypes.PetType:
|
||||
{
|
||||
if (player)
|
||||
{
|
||||
Pet pet = player.GetPet();
|
||||
if (pet)
|
||||
condMeets = (((1 << (int)pet.getPetType()) & ConditionValue1) != 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ConditionTypes.Taxi:
|
||||
{
|
||||
if (player)
|
||||
condMeets = player.IsInFlight();
|
||||
break;
|
||||
}
|
||||
case ConditionTypes.Queststate:
|
||||
{
|
||||
if (player)
|
||||
{
|
||||
if (
|
||||
(Convert.ToBoolean(ConditionValue2 & (1 << (int)QuestStatus.None)) && (player.GetQuestStatus(ConditionValue1) == QuestStatus.None)) ||
|
||||
(Convert.ToBoolean(ConditionValue2 & (1 << (int)QuestStatus.Complete)) && (player.GetQuestStatus(ConditionValue1) == QuestStatus.Complete)) ||
|
||||
(Convert.ToBoolean(ConditionValue2 & (1 << (int)QuestStatus.Incomplete)) && (player.GetQuestStatus(ConditionValue1) == QuestStatus.Incomplete)) ||
|
||||
(Convert.ToBoolean(ConditionValue2 & (1 << (int)QuestStatus.Failed)) && (player.GetQuestStatus(ConditionValue1) == QuestStatus.Failed)) ||
|
||||
(Convert.ToBoolean(ConditionValue2 & (1 << (int)QuestStatus.Rewarded)) && player.GetQuestRewardStatus(ConditionValue1))
|
||||
)
|
||||
condMeets = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ConditionTypes.ObjectiveComplete:
|
||||
{
|
||||
if (player)
|
||||
{
|
||||
QuestObjective questObj = Global.ObjectMgr.GetQuestObjective(ConditionValue1);
|
||||
if (questObj == null)
|
||||
break;
|
||||
|
||||
condMeets = (!player.GetQuestRewardStatus(questObj.QuestID) && player.IsQuestObjectiveComplete(questObj));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
condMeets = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (NegativeCondition)
|
||||
condMeets = !condMeets;
|
||||
|
||||
if (!condMeets)
|
||||
sourceInfo.mLastFailedCondition = this;
|
||||
|
||||
bool script = Global.ScriptMgr.OnConditionCheck(this, sourceInfo); // Returns true by default.
|
||||
return condMeets && script;
|
||||
}
|
||||
|
||||
public GridMapTypeMask GetSearcherTypeMaskForCondition()
|
||||
{
|
||||
// build mask of types for which condition can return true
|
||||
// this is used for speeding up gridsearches
|
||||
if (NegativeCondition)
|
||||
return GridMapTypeMask.All;
|
||||
|
||||
GridMapTypeMask mask = 0;
|
||||
switch (ConditionType)
|
||||
{
|
||||
case ConditionTypes.DistanceTo:
|
||||
case ConditionTypes.WorldState:
|
||||
case ConditionTypes.PhaseId:
|
||||
case ConditionTypes.Spawnmask:
|
||||
case ConditionTypes.NearCreature:
|
||||
case ConditionTypes.NearGameobject:
|
||||
case ConditionTypes.ActiveEvent:
|
||||
case ConditionTypes.InstanceInfo:
|
||||
case ConditionTypes.Mapid:
|
||||
case ConditionTypes.Areaid:
|
||||
case ConditionTypes.None:
|
||||
case ConditionTypes.Zoneid:
|
||||
case ConditionTypes.TerrainSwap:
|
||||
case ConditionTypes.RealmAchievement:
|
||||
mask |= GridMapTypeMask.All;
|
||||
break;
|
||||
case ConditionTypes.Gender:
|
||||
case ConditionTypes.Title:
|
||||
case ConditionTypes.DrunkenState:
|
||||
case ConditionTypes.Spell:
|
||||
case ConditionTypes.QuestTaken:
|
||||
case ConditionTypes.QuestComplete:
|
||||
case ConditionTypes.QuestNone:
|
||||
case ConditionTypes.Skill:
|
||||
case ConditionTypes.QuestRewarded:
|
||||
case ConditionTypes.ReputationRank:
|
||||
case ConditionTypes.Achievement:
|
||||
case ConditionTypes.Team:
|
||||
case ConditionTypes.Item:
|
||||
case ConditionTypes.ItemEquipped:
|
||||
case ConditionTypes.PetType:
|
||||
case ConditionTypes.Taxi:
|
||||
case ConditionTypes.Queststate:
|
||||
mask |= GridMapTypeMask.Player;
|
||||
break;
|
||||
case ConditionTypes.UnitState:
|
||||
case ConditionTypes.Alive:
|
||||
case ConditionTypes.HpVal:
|
||||
case ConditionTypes.HpPct:
|
||||
case ConditionTypes.RelationTo:
|
||||
case ConditionTypes.ReactionTo:
|
||||
case ConditionTypes.Level:
|
||||
case ConditionTypes.Class:
|
||||
case ConditionTypes.Race:
|
||||
case ConditionTypes.Aura:
|
||||
case ConditionTypes.InWater:
|
||||
case ConditionTypes.StandState:
|
||||
mask |= GridMapTypeMask.Creature | GridMapTypeMask.Player;
|
||||
break;
|
||||
case ConditionTypes.ObjectEntryGuid:
|
||||
switch ((TypeId)ConditionValue1)
|
||||
{
|
||||
case TypeId.Unit:
|
||||
mask |= GridMapTypeMask.Creature;
|
||||
break;
|
||||
case TypeId.Player:
|
||||
mask |= GridMapTypeMask.Player;
|
||||
break;
|
||||
case TypeId.GameObject:
|
||||
mask |= GridMapTypeMask.GameObject;
|
||||
break;
|
||||
case TypeId.Corpse:
|
||||
mask |= GridMapTypeMask.Corpse;
|
||||
break;
|
||||
case TypeId.AreaTrigger:
|
||||
mask |= GridMapTypeMask.AreaTrigger;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ConditionTypes.TypeMask:
|
||||
if (Convert.ToBoolean((TypeMask)ConditionValue1 & TypeMask.Unit))
|
||||
mask |= GridMapTypeMask.Creature | GridMapTypeMask.Player;
|
||||
if (Convert.ToBoolean((TypeMask)ConditionValue1 & TypeMask.Player))
|
||||
mask |= GridMapTypeMask.Player;
|
||||
if (Convert.ToBoolean((TypeMask)ConditionValue1 & TypeMask.GameObject))
|
||||
mask |= GridMapTypeMask.GameObject;
|
||||
if (Convert.ToBoolean((TypeMask)ConditionValue1 & TypeMask.Corpse))
|
||||
mask |= GridMapTypeMask.Corpse;
|
||||
if (Convert.ToBoolean((TypeMask)ConditionValue1 & TypeMask.AreaTrigger))
|
||||
mask |= GridMapTypeMask.AreaTrigger;
|
||||
break;
|
||||
case ConditionTypes.DailyQuestDone:
|
||||
case ConditionTypes.ObjectiveComplete:
|
||||
mask |= GridMapTypeMask.Player;
|
||||
break;
|
||||
default:
|
||||
Contract.Assert(false, "Condition.GetSearcherTypeMaskForCondition - missing condition handling!");
|
||||
break;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
public bool isLoaded()
|
||||
{
|
||||
return ConditionType > ConditionTypes.None || ReferenceId != 0;
|
||||
}
|
||||
|
||||
public uint GetMaxAvailableConditionTargets()
|
||||
{
|
||||
// returns number of targets which are available for given source type
|
||||
switch (SourceType)
|
||||
{
|
||||
case ConditionSourceType.Spell:
|
||||
case ConditionSourceType.SpellImplicitTarget:
|
||||
case ConditionSourceType.CreatureTemplateVehicle:
|
||||
case ConditionSourceType.VehicleSpell:
|
||||
case ConditionSourceType.SpellClickEvent:
|
||||
case ConditionSourceType.GossipMenu:
|
||||
case ConditionSourceType.GossipMenuOption:
|
||||
case ConditionSourceType.SmartEvent:
|
||||
case ConditionSourceType.NpcVendor:
|
||||
case ConditionSourceType.SpellProc:
|
||||
return 2;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public string ToString(bool ext = false)
|
||||
{
|
||||
StringBuilder ss = new StringBuilder();
|
||||
ss.AppendFormat("[Condition SourceType: {0}", SourceType);
|
||||
if (SourceType < ConditionSourceType.Max)
|
||||
ss.AppendFormat(" ({0})", Global.ConditionMgr.StaticSourceTypeData[(int)SourceType]);
|
||||
else
|
||||
ss.Append(" (Unknown)");
|
||||
if (Global.ConditionMgr.CanHaveSourceGroupSet(SourceType))
|
||||
ss.AppendFormat(", SourceGroup: {0}", SourceGroup);
|
||||
ss.AppendFormat(", SourceEntry: {0}", SourceEntry);
|
||||
if (Global.ConditionMgr.CanHaveSourceIdSet(SourceType))
|
||||
ss.AppendFormat(", SourceId: {0}", SourceId);
|
||||
|
||||
if (ext)
|
||||
{
|
||||
ss.AppendFormat(", ConditionType: {0}", ConditionType);
|
||||
if (ConditionType < ConditionTypes.Max)
|
||||
ss.AppendFormat(" ({0})", Global.ConditionMgr.StaticConditionTypeData[(int)ConditionType].Name);
|
||||
else
|
||||
ss.Append(" (Unknown)");
|
||||
}
|
||||
|
||||
ss.Append("]");
|
||||
return ss.ToString();
|
||||
}
|
||||
|
||||
public ConditionSourceType SourceType; //SourceTypeOrReferenceId
|
||||
public uint SourceGroup;
|
||||
public int SourceEntry;
|
||||
public uint SourceId; // So far, only used in CONDITION_SOURCE_TYPE_SMART_EVENT
|
||||
public uint ElseGroup;
|
||||
public ConditionTypes ConditionType; //ConditionTypeOrReference
|
||||
public uint ConditionValue1;
|
||||
public uint ConditionValue2;
|
||||
public uint ConditionValue3;
|
||||
public uint ErrorType;
|
||||
public uint ErrorTextId;
|
||||
public uint ReferenceId;
|
||||
public uint ScriptId;
|
||||
public byte ConditionTarget;
|
||||
public bool NegativeCondition;
|
||||
}
|
||||
|
||||
public class ConditionSourceInfo
|
||||
{
|
||||
public ConditionSourceInfo(WorldObject target0, WorldObject target1 = null, WorldObject target2 = null)
|
||||
{
|
||||
mConditionTargets[0] = target0;
|
||||
mConditionTargets[1] = target1;
|
||||
mConditionTargets[2] = target2;
|
||||
mLastFailedCondition = null;
|
||||
}
|
||||
|
||||
public WorldObject[] mConditionTargets = new WorldObject[SharedConst.MaxConditionTargets]; // an array of targets available for conditions
|
||||
public Condition mLastFailedCondition;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Collections;
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
public class DisableManager : Singleton<DisableManager>
|
||||
{
|
||||
DisableManager() { }
|
||||
|
||||
public class DisableData
|
||||
{
|
||||
public byte flags;
|
||||
public List<uint> param0 = new List<uint>();
|
||||
public List<uint> param1 = new List<uint>();
|
||||
}
|
||||
|
||||
Dictionary<DisableType, Dictionary<uint, DisableData>> m_DisableMap = new Dictionary<DisableType, Dictionary<uint, DisableData>>();
|
||||
|
||||
public void LoadDisables()
|
||||
{
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
|
||||
// reload case
|
||||
m_DisableMap.Clear();
|
||||
|
||||
SQLResult result = DB.World.Query("SELECT sourceType, entry, flags, params_0, params_1 FROM disables");
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outError(LogFilter.ServerLoading, "Loaded 0 disables. DB table `disables` is empty!");
|
||||
return;
|
||||
}
|
||||
|
||||
uint total_count = 0;
|
||||
do
|
||||
{
|
||||
DisableType type = (DisableType)result.Read<uint>(0);
|
||||
if (type >= DisableType.Max)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Invalid type {0} specified in `disables` table, skipped.", type);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint entry = result.Read<uint>(1);
|
||||
byte flags = result.Read<byte>(2);
|
||||
string params_0 = result.Read<string>(3);
|
||||
string params_1 = result.Read<string>(4);
|
||||
|
||||
DisableData data = new DisableData();
|
||||
data.flags = flags;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DisableType.Spell:
|
||||
if (!(Global.SpellMgr.HasSpellInfo(entry) || flags.HasAnyFlag<byte>(DisableFlags.SpellDeprecatedSpell)))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Spell entry {0} from `disables` doesn't exist in dbc, skipped.", entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flags == 0 || flags > DisableFlags.MaxSpell)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Disable flags for spell {0} are invalid, skipped.", entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flags.HasAnyFlag<byte>(DisableFlags.SpellMap))
|
||||
{
|
||||
var array = new StringArray(params_0, ',');
|
||||
for (byte i = 0; i < array.Length;)
|
||||
data.param0.Add(uint.Parse(array[i++]));
|
||||
}
|
||||
|
||||
if (flags.HasAnyFlag<byte>(DisableFlags.SpellArea))
|
||||
{
|
||||
var array = new StringArray(params_1, ',');
|
||||
for (byte i = 0; i < array.Length;)
|
||||
data.param1.Add(uint.Parse(array[i++]));
|
||||
}
|
||||
|
||||
break;
|
||||
// checked later
|
||||
case DisableType.Quest:
|
||||
break;
|
||||
case DisableType.Map:
|
||||
{
|
||||
MapRecord mapEntry = CliDB.MapStorage.LookupByKey(entry);
|
||||
if (mapEntry == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Map entry {0} from `disables` doesn't exist in dbc, skipped.", entry);
|
||||
continue;
|
||||
}
|
||||
bool isFlagInvalid = false;
|
||||
switch (mapEntry.InstanceType)
|
||||
{
|
||||
case MapTypes.Common:
|
||||
if (flags != 0)
|
||||
isFlagInvalid = true;
|
||||
break;
|
||||
case MapTypes.Instance:
|
||||
case MapTypes.Raid:
|
||||
if (flags.HasAnyFlag<byte>(DisableFlags.DungeonStatusHeroic) && Global.DB2Mgr.GetMapDifficultyData(entry, Difficulty.Heroic) == null)
|
||||
flags -= DisableFlags.DungeonStatusHeroic;
|
||||
if (flags.HasAnyFlag<byte>(DisableFlags.DungeonStatusHeroic10Man) && Global.DB2Mgr.GetMapDifficultyData(entry, Difficulty.Raid10HC) == null)
|
||||
flags -= DisableFlags.DungeonStatusHeroic10Man;
|
||||
if (flags.HasAnyFlag<byte>(DisableFlags.DungeonStatusHeroic25Man) && Global.DB2Mgr.GetMapDifficultyData(entry, Difficulty.Raid25HC) == null)
|
||||
flags -= DisableFlags.DungeonStatusHeroic25Man;
|
||||
if (flags == 0)
|
||||
isFlagInvalid = true;
|
||||
break;
|
||||
case MapTypes.Battleground:
|
||||
case MapTypes.Arena:
|
||||
Log.outError(LogFilter.Sql, "Battlegroundmap {0} specified to be disabled in map case, skipped.", entry);
|
||||
continue;
|
||||
}
|
||||
if (isFlagInvalid)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Disable flags for map {0} are invalid, skipped.", entry);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DisableType.Battleground:
|
||||
if (!CliDB.BattlemasterListStorage.ContainsKey(entry))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Battlegroundentry {0} from `disables` doesn't exist in dbc, skipped.", entry);
|
||||
continue;
|
||||
}
|
||||
if (flags != 0)
|
||||
Log.outError(LogFilter.Sql, "Disable flags specified for Battleground{0}, useless data.", entry);
|
||||
break;
|
||||
case DisableType.OutdoorPVP:
|
||||
if (entry > (int)OutdoorPvPTypes.Max)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "OutdoorPvPTypes value {0} from `disables` is invalid, skipped.", entry);
|
||||
continue;
|
||||
}
|
||||
if (flags != 0)
|
||||
Log.outError(LogFilter.Sql, "Disable flags specified for outdoor PvP {0}, useless data.", entry);
|
||||
break;
|
||||
case DisableType.Criteria:
|
||||
if (Global.CriteriaMgr.GetCriteria(entry) == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Criteria entry {0} from `disables` doesn't exist in dbc, skipped.", entry);
|
||||
continue;
|
||||
}
|
||||
if (flags != 0)
|
||||
Log.outError(LogFilter.Sql, "Disable flags specified for Criteria {0}, useless data.", entry);
|
||||
break;
|
||||
case DisableType.VMAP:
|
||||
{
|
||||
MapRecord mapEntry = CliDB.MapStorage.LookupByKey(entry);
|
||||
if (mapEntry == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Map entry {0} from `disables` doesn't exist in dbc, skipped.", entry);
|
||||
continue;
|
||||
}
|
||||
switch (mapEntry.InstanceType)
|
||||
{
|
||||
case MapTypes.Common:
|
||||
if (flags.HasAnyFlag(DisableFlags.VmapAreaFlag))
|
||||
Log.outInfo(LogFilter.Server, "Areaflag disabled for world map {0}.", entry);
|
||||
if (flags.HasAnyFlag(DisableFlags.VmapLiquidStatus))
|
||||
Log.outInfo(LogFilter.Server, "Liquid status disabled for world map {0}.", entry);
|
||||
break;
|
||||
case MapTypes.Instance:
|
||||
case MapTypes.Raid:
|
||||
if (flags.HasAnyFlag(DisableFlags.VmapHeight))
|
||||
Log.outInfo(LogFilter.Server, "Height disabled for instance map {0}.", entry);
|
||||
if (flags.HasAnyFlag(DisableFlags.VmapLOS))
|
||||
Log.outInfo(LogFilter.Server, "LoS disabled for instance map {0}.", entry);
|
||||
break;
|
||||
case MapTypes.Battleground:
|
||||
if (flags.HasAnyFlag(DisableFlags.VmapHeight))
|
||||
Log.outInfo(LogFilter.Server, "Height disabled for Battlegroundmap {0}.", entry);
|
||||
if (flags.HasAnyFlag(DisableFlags.VmapLOS))
|
||||
Log.outInfo(LogFilter.Server, "LoS disabled for Battlegroundmap {0}.", entry);
|
||||
break;
|
||||
case MapTypes.Arena:
|
||||
if (flags.HasAnyFlag(DisableFlags.VmapHeight))
|
||||
Log.outInfo(LogFilter.Server, "Height disabled for arena map {0}.", entry);
|
||||
if (flags.HasAnyFlag(DisableFlags.VmapLOS))
|
||||
Log.outInfo(LogFilter.Server, "LoS disabled for arena map {0}.", entry);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DisableType.MMAP:
|
||||
{
|
||||
MapRecord mapEntry = CliDB.MapStorage.LookupByKey(entry);
|
||||
if (mapEntry == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Map entry {0} from `disables` doesn't exist in dbc, skipped.", entry);
|
||||
continue;
|
||||
}
|
||||
switch (mapEntry.InstanceType)
|
||||
{
|
||||
case MapTypes.Common:
|
||||
Log.outInfo(LogFilter.Server, "Pathfinding disabled for world map {0}.", entry);
|
||||
break;
|
||||
case MapTypes.Instance:
|
||||
case MapTypes.Raid:
|
||||
Log.outInfo(LogFilter.Server, "Pathfinding disabled for instance map {0}.", entry);
|
||||
break;
|
||||
case MapTypes.Battleground:
|
||||
Log.outInfo(LogFilter.Server, "Pathfinding disabled for Battlegroundmap {0}.", entry);
|
||||
break;
|
||||
case MapTypes.Arena:
|
||||
Log.outInfo(LogFilter.Server, "Pathfinding disabled for arena map {0}.", entry);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!m_DisableMap.ContainsKey(type))
|
||||
m_DisableMap[type] = new Dictionary<uint, DisableData>();
|
||||
|
||||
m_DisableMap[type].Add(entry, data);
|
||||
++total_count;
|
||||
}
|
||||
while (result.NextRow());
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} disables in {1} ms", total_count, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
public void CheckQuestDisables()
|
||||
{
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
|
||||
int count = m_DisableMap[DisableType.Quest].Count;
|
||||
if (count == 0)
|
||||
{
|
||||
Log.outInfo(LogFilter.ServerLoading, "Checked 0 quest disables.");
|
||||
return;
|
||||
}
|
||||
|
||||
// check only quests, rest already done at startup
|
||||
foreach (var pair in m_DisableMap[DisableType.Quest])
|
||||
{
|
||||
uint entry = pair.Key;
|
||||
if (Global.ObjectMgr.GetQuestTemplate(entry) == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Quest entry {0} from `disables` doesn't exist, skipped.", entry);
|
||||
m_DisableMap[DisableType.Quest].Remove(entry);
|
||||
continue;
|
||||
}
|
||||
if (pair.Value.flags != 0)
|
||||
Log.outError(LogFilter.Sql, "Disable flags specified for quest {0}, useless data.", entry);
|
||||
}
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Checked {0} quest disables in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
public bool IsDisabledFor(DisableType type, uint entry, Unit unit, byte flags = 0)
|
||||
{
|
||||
Contract.Assert(type < DisableType.Max);
|
||||
if (!m_DisableMap.ContainsKey(type) || m_DisableMap[type].Empty())
|
||||
return false;
|
||||
|
||||
var data = m_DisableMap[type].LookupByKey(entry);
|
||||
if (data == null) // not disabled
|
||||
return false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DisableType.Spell:
|
||||
{
|
||||
byte spellFlags = data.flags;
|
||||
if (unit != null)
|
||||
{
|
||||
if ((spellFlags.HasAnyFlag(DisableFlags.SpellPlayer) && unit.IsTypeId(TypeId.Player)) ||
|
||||
(unit.IsTypeId(TypeId.Unit) && ((unit.IsPet() && spellFlags.HasAnyFlag(DisableFlags.SpellPet)) || spellFlags.HasAnyFlag(DisableFlags.SpellCreature))))
|
||||
{
|
||||
if (spellFlags.HasAnyFlag(DisableFlags.SpellMap))
|
||||
{
|
||||
List<uint> mapIds = data.param0;
|
||||
if (mapIds.Contains(unit.GetMapId()))
|
||||
return true; // Spell is disabled on current map
|
||||
|
||||
if (!spellFlags.HasAnyFlag(DisableFlags.SpellArea))
|
||||
return false; // Spell is disabled on another map, but not this one, return false
|
||||
|
||||
// Spell is disabled in an area, but not explicitly our current mapId. Continue processing.
|
||||
}
|
||||
|
||||
if (spellFlags.HasAnyFlag(DisableFlags.SpellArea))
|
||||
{
|
||||
var areaIds = data.param1;
|
||||
if (areaIds.Contains(unit.GetAreaId()))
|
||||
return true; // Spell is disabled in this area
|
||||
return false; // Spell is disabled in another area, but not this one, return false
|
||||
}
|
||||
else
|
||||
return true; // Spell disabled for all maps
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (spellFlags.HasAnyFlag(DisableFlags.SpellDeprecatedSpell)) // call not from spellcast
|
||||
return true;
|
||||
else if (flags.HasAnyFlag(DisableFlags.SpellLOS))
|
||||
return spellFlags.HasAnyFlag(DisableFlags.SpellLOS);
|
||||
|
||||
break;
|
||||
}
|
||||
case DisableType.Map:
|
||||
Player player = unit.ToPlayer();
|
||||
if (player != null)
|
||||
{
|
||||
MapRecord mapEntry = CliDB.MapStorage.LookupByKey(entry);
|
||||
if (mapEntry.IsDungeon())
|
||||
{
|
||||
byte disabledModes = data.flags;
|
||||
Difficulty targetDifficulty = player.GetDifficultyID(mapEntry);
|
||||
Global.DB2Mgr.GetDownscaledMapDifficultyData(entry, ref targetDifficulty);
|
||||
switch (targetDifficulty)
|
||||
{
|
||||
case Difficulty.Normal:
|
||||
return disabledModes.HasAnyFlag(DisableFlags.DungeonStatusNormal);
|
||||
case Difficulty.Heroic:
|
||||
return disabledModes.HasAnyFlag(DisableFlags.DungeonStatusHeroic);
|
||||
case Difficulty.Raid10HC:
|
||||
return disabledModes.HasAnyFlag(DisableFlags.DungeonStatusHeroic10Man);
|
||||
case Difficulty.Raid25HC:
|
||||
return disabledModes.HasAnyFlag(DisableFlags.DungeonStatusHeroic25Man);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (mapEntry.InstanceType == MapTypes.Common)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case DisableType.Quest:
|
||||
if (unit == null)
|
||||
return true;
|
||||
Player player1 = unit.ToPlayer();
|
||||
if (player1 != null)
|
||||
if (player1.IsGameMaster())
|
||||
return false;
|
||||
return true;
|
||||
case DisableType.Battleground:
|
||||
case DisableType.OutdoorPVP:
|
||||
case DisableType.Criteria:
|
||||
case DisableType.MMAP:
|
||||
return true;
|
||||
case DisableType.VMAP:
|
||||
return flags.HasAnyFlag(data.flags);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsVMAPDisabledFor(uint entry, byte flags)
|
||||
{
|
||||
return IsDisabledFor(DisableType.VMAP, entry, null, flags);
|
||||
}
|
||||
|
||||
public bool IsPathfindingEnabled(uint mapId)
|
||||
{
|
||||
return WorldConfig.GetBoolValue(WorldCfg.EnableMmaps) && !Global.DisableMgr.IsDisabledFor(DisableType.MMAP, mapId, null);
|
||||
}
|
||||
}
|
||||
|
||||
public enum DisableType
|
||||
{
|
||||
Spell = 0,
|
||||
Quest = 1,
|
||||
Map = 2,
|
||||
Battleground= 3,
|
||||
Criteria = 4,
|
||||
OutdoorPVP = 5,
|
||||
VMAP = 6,
|
||||
MMAP = 7,
|
||||
Max = 8
|
||||
}
|
||||
|
||||
public struct DisableFlags
|
||||
{
|
||||
public const byte SpellPlayer = 0x1;
|
||||
public const byte SpellCreature = 0x2;
|
||||
public const byte SpellPet = 0x4;
|
||||
public const byte SpellDeprecatedSpell = 0x8;
|
||||
public const byte SpellMap = 0x10;
|
||||
public const byte SpellArea = 0x20;
|
||||
public const byte SpellLOS = 0x40;
|
||||
public const byte MaxSpell = (SpellPlayer | SpellCreature | SpellPet | SpellDeprecatedSpell | SpellMap | SpellArea | SpellLOS);
|
||||
|
||||
public const byte VmapAreaFlag = 0x1;
|
||||
public const byte VmapHeight = 0x2;
|
||||
public const byte VmapLOS = 0x4;
|
||||
public const byte VmapLiquidStatus = 0x8;
|
||||
|
||||
public const byte MMapPathFinding = 0x0;
|
||||
|
||||
public const byte DungeonStatusNormal = 0x01;
|
||||
public const byte DungeonStatusHeroic = 0x02;
|
||||
|
||||
public const byte DungeonStatusNormal10Man = 0x01;
|
||||
public const byte DungeonStatusNormal25Man = 0x02;
|
||||
public const byte DungeonStatusHeroic10Man = 0x04;
|
||||
public const byte DungeonStatusHeroic25Man = 0x08;
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user