Core/SAI: Warn when an unused parameter is set in the database
Port From (https://github.com/TrinityCore/TrinityCore/commit/c9e685bd9a0ac524edb8fe64eb6ec37540c55acc)
This commit is contained in:
@@ -62,7 +62,7 @@ namespace Game.AI
|
|||||||
temp.EntryOrGuid = result.Read<int>(0);
|
temp.EntryOrGuid = result.Read<int>(0);
|
||||||
if (temp.EntryOrGuid == 0)
|
if (temp.EntryOrGuid == 0)
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Sql, "SmartAIMgr::LoadFromDB: invalid entryorguid (0), skipped loading.");
|
Log.outError(LogFilter.Sql, "SmartAIMgr.LoadFromDB: invalid entryorguid (0), skipped loading.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,9 +514,8 @@ namespace Game.AI
|
|||||||
TC_SAI_IS_BOOLEAN_VALID(e, e.Target.farthest.playerOnly);
|
TC_SAI_IS_BOOLEAN_VALID(e, e.Target.farthest.playerOnly);
|
||||||
TC_SAI_IS_BOOLEAN_VALID(e, e.Target.farthest.isInLos);
|
TC_SAI_IS_BOOLEAN_VALID(e, e.Target.farthest.isInLos);
|
||||||
break;
|
break;
|
||||||
case SmartTargets.ClosestGameobject:
|
|
||||||
case SmartTargets.ClosestCreature:
|
case SmartTargets.ClosestCreature:
|
||||||
TC_SAI_IS_BOOLEAN_VALID(e, e.Target.closest.dead);
|
TC_SAI_IS_BOOLEAN_VALID(e, e.Target.unitClosest.dead);
|
||||||
break;
|
break;
|
||||||
case SmartTargets.ClosestEnemy:
|
case SmartTargets.ClosestEnemy:
|
||||||
TC_SAI_IS_BOOLEAN_VALID(e, e.Target.closestAttackable.playerOnly);
|
TC_SAI_IS_BOOLEAN_VALID(e, e.Target.closestAttackable.playerOnly);
|
||||||
@@ -527,6 +526,7 @@ namespace Game.AI
|
|||||||
case SmartTargets.OwnerOrSummoner:
|
case SmartTargets.OwnerOrSummoner:
|
||||||
TC_SAI_IS_BOOLEAN_VALID(e, e.Target.owner.useCharmerOrOwner);
|
TC_SAI_IS_BOOLEAN_VALID(e, e.Target.owner.useCharmerOrOwner);
|
||||||
break;
|
break;
|
||||||
|
case SmartTargets.ClosestGameobject:
|
||||||
case SmartTargets.PlayerRange:
|
case SmartTargets.PlayerRange:
|
||||||
case SmartTargets.Self:
|
case SmartTargets.Self:
|
||||||
case SmartTargets.Victim:
|
case SmartTargets.Victim:
|
||||||
@@ -542,6 +542,10 @@ namespace Game.AI
|
|||||||
Log.outError(LogFilter.ScriptsAi, "SmartAIMgr: Not handled target_type({0}), Entry {1} SourceType {2} Event {3} Action {4}, skipped.", e.GetTargetType(), e.EntryOrGuid, e.GetScriptType(), e.EventId, e.GetActionType());
|
Log.outError(LogFilter.ScriptsAi, "SmartAIMgr: Not handled target_type({0}), Entry {1} SourceType {2} Event {3} Action {4}, skipped.", e.GetTargetType(), e.EntryOrGuid, e.GetScriptType(), e.EventId, e.GetActionType());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!CheckUnusedTargetParams(e))
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,6 +559,398 @@ namespace Game.AI
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool CheckUnusedEventParams(SmartScriptHolder e)
|
||||||
|
{
|
||||||
|
int paramsStructSize = e.Event.type switch
|
||||||
|
{
|
||||||
|
SmartEvents.UpdateIc => Marshal.SizeOf(typeof(SmartEvent.MinMaxRepeat)),
|
||||||
|
SmartEvents.UpdateOoc => Marshal.SizeOf(typeof(SmartEvent.MinMaxRepeat)),
|
||||||
|
SmartEvents.HealthPct => Marshal.SizeOf(typeof(SmartEvent.MinMaxRepeat)),
|
||||||
|
SmartEvents.ManaPct => Marshal.SizeOf(typeof(SmartEvent.MinMaxRepeat)),
|
||||||
|
SmartEvents.Aggro => 0,
|
||||||
|
SmartEvents.Kill => Marshal.SizeOf(typeof(SmartEvent.Kill)),
|
||||||
|
SmartEvents.Death => 0,
|
||||||
|
SmartEvents.Evade => 0,
|
||||||
|
SmartEvents.SpellHit => Marshal.SizeOf(typeof(SmartEvent.SpellHit)),
|
||||||
|
SmartEvents.Range => Marshal.SizeOf(typeof(SmartEvent.MinMaxRepeat)),
|
||||||
|
SmartEvents.OocLos => Marshal.SizeOf(typeof(SmartEvent.Los)),
|
||||||
|
SmartEvents.Respawn => Marshal.SizeOf(typeof(SmartEvent.Respawn)),
|
||||||
|
SmartEvents.TargetHealthPct => Marshal.SizeOf(typeof(SmartEvent.MinMaxRepeat)),
|
||||||
|
SmartEvents.VictimCasting => Marshal.SizeOf(typeof(SmartEvent.TargetCasting)),
|
||||||
|
SmartEvents.FriendlyHealth => Marshal.SizeOf(typeof(SmartEvent.FriendlyHealth)),
|
||||||
|
SmartEvents.FriendlyIsCc => Marshal.SizeOf(typeof(SmartEvent.FriendlyCC)),
|
||||||
|
SmartEvents.FriendlyMissingBuff => Marshal.SizeOf(typeof(SmartEvent.MissingBuff)),
|
||||||
|
SmartEvents.SummonedUnit => Marshal.SizeOf(typeof(SmartEvent.Summoned)),
|
||||||
|
SmartEvents.TargetManaPct => Marshal.SizeOf(typeof(SmartEvent.MinMaxRepeat)),
|
||||||
|
SmartEvents.AcceptedQuest => Marshal.SizeOf(typeof(SmartEvent.Quest)),
|
||||||
|
SmartEvents.RewardQuest => Marshal.SizeOf(typeof(SmartEvent.Quest)),
|
||||||
|
SmartEvents.ReachedHome => 0,
|
||||||
|
SmartEvents.ReceiveEmote => Marshal.SizeOf(typeof(SmartEvent.Emote)),
|
||||||
|
SmartEvents.HasAura => Marshal.SizeOf(typeof(SmartEvent.Aura)),
|
||||||
|
SmartEvents.TargetBuffed => Marshal.SizeOf(typeof(SmartEvent.Aura)),
|
||||||
|
SmartEvents.Reset => 0,
|
||||||
|
SmartEvents.IcLos => Marshal.SizeOf(typeof(SmartEvent.Los)),
|
||||||
|
SmartEvents.PassengerBoarded => Marshal.SizeOf(typeof(SmartEvent.MinMax)),
|
||||||
|
SmartEvents.PassengerRemoved => Marshal.SizeOf(typeof(SmartEvent.MinMax)),
|
||||||
|
SmartEvents.Charmed => Marshal.SizeOf(typeof(SmartEvent.Charm)),
|
||||||
|
SmartEvents.CharmedTarget => 0,
|
||||||
|
SmartEvents.SpellHitTarget => Marshal.SizeOf(typeof(SmartEvent.SpellHit)),
|
||||||
|
SmartEvents.Damaged => Marshal.SizeOf(typeof(SmartEvent.MinMaxRepeat)),
|
||||||
|
SmartEvents.DamagedTarget => Marshal.SizeOf(typeof(SmartEvent.MinMaxRepeat)),
|
||||||
|
SmartEvents.Movementinform => Marshal.SizeOf(typeof(SmartEvent.MovementInform)),
|
||||||
|
SmartEvents.SummonDespawned => Marshal.SizeOf(typeof(SmartEvent.Summoned)),
|
||||||
|
SmartEvents.CorpseRemoved => 0,
|
||||||
|
SmartEvents.AiInit => 0,
|
||||||
|
SmartEvents.DataSet => Marshal.SizeOf(typeof(SmartEvent.DataSet)),
|
||||||
|
SmartEvents.WaypointStart => Marshal.SizeOf(typeof(SmartEvent.Waypoint)),
|
||||||
|
SmartEvents.WaypointReached => Marshal.SizeOf(typeof(SmartEvent.Waypoint)),
|
||||||
|
SmartEvents.TransportAddplayer => 0,
|
||||||
|
SmartEvents.TransportAddcreature => Marshal.SizeOf(typeof(SmartEvent.TransportAddCreature)),
|
||||||
|
SmartEvents.TransportRemovePlayer => 0,
|
||||||
|
SmartEvents.TransportRelocate => Marshal.SizeOf(typeof(SmartEvent.TransportRelocate)),
|
||||||
|
SmartEvents.InstancePlayerEnter => Marshal.SizeOf(typeof(SmartEvent.InstancePlayerEnter)),
|
||||||
|
SmartEvents.AreatriggerOntrigger => Marshal.SizeOf(typeof(SmartEvent.Areatrigger)),
|
||||||
|
SmartEvents.QuestAccepted => 0,
|
||||||
|
SmartEvents.QuestObjCompletion => 0,
|
||||||
|
SmartEvents.QuestCompletion => 0,
|
||||||
|
SmartEvents.QuestRewarded => 0,
|
||||||
|
SmartEvents.QuestFail => 0,
|
||||||
|
SmartEvents.TextOver => Marshal.SizeOf(typeof(SmartEvent.TextOver)),
|
||||||
|
SmartEvents.ReceiveHeal => Marshal.SizeOf(typeof(SmartEvent.MinMaxRepeat)),
|
||||||
|
SmartEvents.JustSummoned => 0,
|
||||||
|
SmartEvents.WaypointPaused => Marshal.SizeOf(typeof(SmartEvent.Waypoint)),
|
||||||
|
SmartEvents.WaypointResumed => Marshal.SizeOf(typeof(SmartEvent.Waypoint)),
|
||||||
|
SmartEvents.WaypointStopped => Marshal.SizeOf(typeof(SmartEvent.Waypoint)),
|
||||||
|
SmartEvents.WaypointEnded => Marshal.SizeOf(typeof(SmartEvent.Waypoint)),
|
||||||
|
SmartEvents.TimedEventTriggered => Marshal.SizeOf(typeof(SmartEvent.TimedEvent)),
|
||||||
|
SmartEvents.Update => Marshal.SizeOf(typeof(SmartEvent.MinMaxRepeat)),
|
||||||
|
SmartEvents.Link => 0,
|
||||||
|
SmartEvents.GossipSelect => Marshal.SizeOf(typeof(SmartEvent.Gossip)),
|
||||||
|
SmartEvents.JustCreated => 0,
|
||||||
|
SmartEvents.GossipHello => Marshal.SizeOf(typeof(SmartEvent.GossipHello)),
|
||||||
|
SmartEvents.FollowCompleted => 0,
|
||||||
|
SmartEvents.PhaseChange => Marshal.SizeOf(typeof(SmartEvent.EventPhaseChange)),
|
||||||
|
SmartEvents.IsBehindTarget => Marshal.SizeOf(typeof(SmartEvent.BehindTarget)),
|
||||||
|
SmartEvents.GameEventStart => Marshal.SizeOf(typeof(SmartEvent.GameEvent)),
|
||||||
|
SmartEvents.GameEventEnd => Marshal.SizeOf(typeof(SmartEvent.GameEvent)),
|
||||||
|
SmartEvents.GoLootStateChanged => Marshal.SizeOf(typeof(SmartEvent.GoLootStateChanged)),
|
||||||
|
SmartEvents.GoEventInform => Marshal.SizeOf(typeof(SmartEvent.EventInform)),
|
||||||
|
SmartEvents.ActionDone => Marshal.SizeOf(typeof(SmartEvent.DoAction)),
|
||||||
|
SmartEvents.OnSpellclick => 0,
|
||||||
|
SmartEvents.FriendlyHealthPCT => Marshal.SizeOf(typeof(SmartEvent.FriendlyHealthPct)),
|
||||||
|
SmartEvents.DistanceCreature => Marshal.SizeOf(typeof(SmartEvent.Distance)),
|
||||||
|
SmartEvents.DistanceGameobject => Marshal.SizeOf(typeof(SmartEvent.Distance)),
|
||||||
|
SmartEvents.CounterSet => Marshal.SizeOf(typeof(SmartEvent.Counter)),
|
||||||
|
SmartEvents.SceneStart => 0,
|
||||||
|
SmartEvents.SceneTrigger => 0,
|
||||||
|
SmartEvents.SceneCancel => 0,
|
||||||
|
SmartEvents.SceneComplete => 0,
|
||||||
|
SmartEvents.SummonedUnitDies => Marshal.SizeOf(typeof(SmartEvent.Summoned)),
|
||||||
|
_ => Marshal.SizeOf(typeof(SmartEvent.Raw)),
|
||||||
|
};
|
||||||
|
|
||||||
|
int rawCount = Marshal.SizeOf(typeof(SmartEvent.Raw)) / sizeof(uint);
|
||||||
|
int paramsCount = paramsStructSize / sizeof(uint);
|
||||||
|
|
||||||
|
bool valid = true;
|
||||||
|
for (int index = paramsCount; index < rawCount; index++)
|
||||||
|
{
|
||||||
|
uint value = 0;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
value = e.Event.raw.param1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
value = e.Event.raw.param2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
value = e.Event.raw.param3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
value = e.Event.raw.param4;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
value = e.Event.raw.param5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value != 0)
|
||||||
|
{
|
||||||
|
Log.outError(LogFilter.Sql, $"SmartAIMgr: {e} has unused event_param{index + 1} with value {value}, it must be 0, skipped.");
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CheckUnusedActionParams(SmartScriptHolder e)
|
||||||
|
{
|
||||||
|
int paramsStructSize = e.Action.type switch
|
||||||
|
{
|
||||||
|
SmartActions.None => 0,
|
||||||
|
SmartActions.Talk => Marshal.SizeOf(typeof(SmartAction.Talk)),
|
||||||
|
SmartActions.SetFaction => Marshal.SizeOf(typeof(SmartAction.Faction)),
|
||||||
|
SmartActions.MorphToEntryOrModel => Marshal.SizeOf(typeof(SmartAction.MorphOrMount)),
|
||||||
|
SmartActions.Sound => Marshal.SizeOf(typeof(SmartAction.Sound)),
|
||||||
|
SmartActions.PlayEmote => Marshal.SizeOf(typeof(SmartAction.Emote)),
|
||||||
|
SmartActions.FailQuest => Marshal.SizeOf(typeof(SmartAction.Quest)),
|
||||||
|
SmartActions.OfferQuest => Marshal.SizeOf(typeof(SmartAction.QuestOffer)),
|
||||||
|
SmartActions.SetReactState => Marshal.SizeOf(typeof(SmartAction.React)),
|
||||||
|
SmartActions.ActivateGobject => 0,
|
||||||
|
SmartActions.RandomEmote => Marshal.SizeOf(typeof(SmartAction.RandomEmote)),
|
||||||
|
SmartActions.Cast => Marshal.SizeOf(typeof(SmartAction.Cast)),
|
||||||
|
SmartActions.SummonCreature => Marshal.SizeOf(typeof(SmartAction.SummonCreature)),
|
||||||
|
SmartActions.ThreatSinglePct => Marshal.SizeOf(typeof(SmartAction.ThreatPCT)),
|
||||||
|
SmartActions.ThreatAllPct => Marshal.SizeOf(typeof(SmartAction.ThreatPCT)),
|
||||||
|
SmartActions.CallAreaexploredoreventhappens => Marshal.SizeOf(typeof(SmartAction.Quest)),
|
||||||
|
SmartActions.SetIngamePhaseGroup => Marshal.SizeOf(typeof(SmartAction.IngamePhaseGroup)),
|
||||||
|
SmartActions.SetEmoteState => Marshal.SizeOf(typeof(SmartAction.Emote)),
|
||||||
|
SmartActions.SetUnitFlag => Marshal.SizeOf(typeof(SmartAction.UnitFlag)),
|
||||||
|
SmartActions.RemoveUnitFlag => Marshal.SizeOf(typeof(SmartAction.UnitFlag)),
|
||||||
|
SmartActions.AutoAttack => Marshal.SizeOf(typeof(SmartAction.AutoAttack)),
|
||||||
|
SmartActions.AllowCombatMovement => Marshal.SizeOf(typeof(SmartAction.CombatMove)),
|
||||||
|
SmartActions.SetEventPhase => Marshal.SizeOf(typeof(SmartAction.SetEventPhase)),
|
||||||
|
SmartActions.IncEventPhase => Marshal.SizeOf(typeof(SmartAction.IncEventPhase)),
|
||||||
|
SmartActions.Evade => Marshal.SizeOf(typeof(SmartAction.Evade)),
|
||||||
|
SmartActions.FleeForAssist => Marshal.SizeOf(typeof(SmartAction.FleeAssist)),
|
||||||
|
SmartActions.CallGroupeventhappens => Marshal.SizeOf(typeof(SmartAction.Quest)),
|
||||||
|
SmartActions.CombatStop => 0,
|
||||||
|
SmartActions.RemoveAurasFromSpell => Marshal.SizeOf(typeof(SmartAction.RemoveAura)),
|
||||||
|
SmartActions.Follow => Marshal.SizeOf(typeof(SmartAction.Follow)),
|
||||||
|
SmartActions.RandomPhase => Marshal.SizeOf(typeof(SmartAction.RandomPhase)),
|
||||||
|
SmartActions.RandomPhaseRange => Marshal.SizeOf(typeof(SmartAction.RandomPhaseRange)),
|
||||||
|
SmartActions.ResetGobject => 0,
|
||||||
|
SmartActions.CallKilledmonster => Marshal.SizeOf(typeof(SmartAction.KilledMonster)),
|
||||||
|
SmartActions.SetInstData => Marshal.SizeOf(typeof(SmartAction.SetInstanceData)),
|
||||||
|
SmartActions.SetInstData64 => Marshal.SizeOf(typeof(SmartAction.SetInstanceData64)),
|
||||||
|
SmartActions.UpdateTemplate => Marshal.SizeOf(typeof(SmartAction.UpdateTemplate)),
|
||||||
|
SmartActions.Die => 0,
|
||||||
|
SmartActions.SetInCombatWithZone => 0,
|
||||||
|
SmartActions.CallForHelp => Marshal.SizeOf(typeof(SmartAction.CallHelp)),
|
||||||
|
SmartActions.SetSheath => Marshal.SizeOf(typeof(SmartAction.SetSheath)),
|
||||||
|
SmartActions.ForceDespawn => Marshal.SizeOf(typeof(SmartAction.ForceDespawn)),
|
||||||
|
SmartActions.SetInvincibilityHpLevel => Marshal.SizeOf(typeof(SmartAction.InvincHP)),
|
||||||
|
SmartActions.MountToEntryOrModel => Marshal.SizeOf(typeof(SmartAction.MorphOrMount)),
|
||||||
|
SmartActions.SetIngamePhaseId => Marshal.SizeOf(typeof(SmartAction.IngamePhaseId)),
|
||||||
|
SmartActions.SetData => Marshal.SizeOf(typeof(SmartAction.SetData)),
|
||||||
|
SmartActions.AttackStop => 0,
|
||||||
|
SmartActions.SetVisibility => Marshal.SizeOf(typeof(SmartAction.Visibility)),
|
||||||
|
SmartActions.SetActive => Marshal.SizeOf(typeof(SmartAction.Active)),
|
||||||
|
SmartActions.AttackStart => 0,
|
||||||
|
SmartActions.SummonGo => Marshal.SizeOf(typeof(SmartAction.SummonGO)),
|
||||||
|
SmartActions.KillUnit => 0,
|
||||||
|
SmartActions.ActivateTaxi => Marshal.SizeOf(typeof(SmartAction.Taxi)),
|
||||||
|
SmartActions.WpStart => Marshal.SizeOf(typeof(SmartAction.WpStart)),
|
||||||
|
SmartActions.WpPause => Marshal.SizeOf(typeof(SmartAction.WpPause)),
|
||||||
|
SmartActions.WpStop => Marshal.SizeOf(typeof(SmartAction.WpStop)),
|
||||||
|
SmartActions.AddItem => Marshal.SizeOf(typeof(SmartAction.Item)),
|
||||||
|
SmartActions.RemoveItem => Marshal.SizeOf(typeof(SmartAction.Item)),
|
||||||
|
SmartActions.InstallAiTemplate => Marshal.SizeOf(typeof(SmartAction.InstallTtemplate)),
|
||||||
|
SmartActions.SetRun => Marshal.SizeOf(typeof(SmartAction.SetRun)),
|
||||||
|
SmartActions.SetDisableGravity => Marshal.SizeOf(typeof(SmartAction.SetDisableGravity)),
|
||||||
|
SmartActions.SetSwim => Marshal.SizeOf(typeof(SmartAction.SetSwim)),
|
||||||
|
SmartActions.Teleport => Marshal.SizeOf(typeof(SmartAction.Teleport)),
|
||||||
|
SmartActions.SetCounter => Marshal.SizeOf(typeof(SmartAction.SetCounter)),
|
||||||
|
SmartActions.StoreTargetList => Marshal.SizeOf(typeof(SmartAction.StoreTargets)),
|
||||||
|
SmartActions.WpResume => 0,
|
||||||
|
SmartActions.SetOrientation => 0,
|
||||||
|
SmartActions.CreateTimedEvent => Marshal.SizeOf(typeof(SmartAction.TimeEvent)),
|
||||||
|
SmartActions.Playmovie => Marshal.SizeOf(typeof(SmartAction.Movie)),
|
||||||
|
SmartActions.MoveToPos => Marshal.SizeOf(typeof(SmartAction.MoveToPos)),
|
||||||
|
SmartActions.EnableTempGobj => Marshal.SizeOf(typeof(SmartAction.EnableTempGO)),
|
||||||
|
SmartActions.Equip => Marshal.SizeOf(typeof(SmartAction.Equip)),
|
||||||
|
SmartActions.CloseGossip => 0,
|
||||||
|
SmartActions.TriggerTimedEvent => Marshal.SizeOf(typeof(SmartAction.TimeEvent)),
|
||||||
|
SmartActions.RemoveTimedEvent => Marshal.SizeOf(typeof(SmartAction.TimeEvent)),
|
||||||
|
SmartActions.AddAura => Marshal.SizeOf(typeof(SmartAction.AddAura)),
|
||||||
|
SmartActions.OverrideScriptBaseObject => 0,
|
||||||
|
SmartActions.ResetScriptBaseObject => 0,
|
||||||
|
SmartActions.CallScriptReset => 0,
|
||||||
|
SmartActions.SetRangedMovement => Marshal.SizeOf(typeof(SmartAction.SetRangedMovement)),
|
||||||
|
SmartActions.CallTimedActionlist => Marshal.SizeOf(typeof(SmartAction.TimedActionList)),
|
||||||
|
SmartActions.SetNpcFlag => Marshal.SizeOf(typeof(SmartAction.Flag)),
|
||||||
|
SmartActions.AddNpcFlag => Marshal.SizeOf(typeof(SmartAction.Flag)),
|
||||||
|
SmartActions.RemoveNpcFlag => Marshal.SizeOf(typeof(SmartAction.Flag)),
|
||||||
|
SmartActions.SimpleTalk => Marshal.SizeOf(typeof(SmartAction.SimpleTalk)),
|
||||||
|
SmartActions.SelfCast => Marshal.SizeOf(typeof(SmartAction.Cast)),
|
||||||
|
SmartActions.CrossCast => Marshal.SizeOf(typeof(SmartAction.CrossCast)),
|
||||||
|
SmartActions.CallRandomTimedActionlist => Marshal.SizeOf(typeof(SmartAction.RandTimedActionList)),
|
||||||
|
SmartActions.CallRandomRangeTimedActionlist => Marshal.SizeOf(typeof(SmartAction.RandRangeTimedActionList)),
|
||||||
|
SmartActions.RandomMove => Marshal.SizeOf(typeof(SmartAction.MoveRandom)),
|
||||||
|
SmartActions.SetUnitFieldBytes1 => Marshal.SizeOf(typeof(SmartAction.SetunitByte)),
|
||||||
|
SmartActions.RemoveUnitFieldBytes1 => Marshal.SizeOf(typeof(SmartAction.DelunitByte)),
|
||||||
|
SmartActions.InterruptSpell => Marshal.SizeOf(typeof(SmartAction.InterruptSpellCasting)),
|
||||||
|
SmartActions.SendGoCustomAnim => Marshal.SizeOf(typeof(SmartAction.SendGoCustomAnim)),
|
||||||
|
SmartActions.SetDynamicFlag => Marshal.SizeOf(typeof(SmartAction.Flag)),
|
||||||
|
SmartActions.AddDynamicFlag => Marshal.SizeOf(typeof(SmartAction.Flag)),
|
||||||
|
SmartActions.RemoveDynamicFlag => Marshal.SizeOf(typeof(SmartAction.Flag)),
|
||||||
|
SmartActions.JumpToPos => Marshal.SizeOf(typeof(SmartAction.Jump)),
|
||||||
|
SmartActions.SendGossipMenu => Marshal.SizeOf(typeof(SmartAction.SendGossipMenu)),
|
||||||
|
SmartActions.GoSetLootState => Marshal.SizeOf(typeof(SmartAction.SetGoLootState)),
|
||||||
|
SmartActions.SendTargetToTarget => Marshal.SizeOf(typeof(SmartAction.SendTargetToTarget)),
|
||||||
|
SmartActions.SetHomePos => 0,
|
||||||
|
SmartActions.SetHealthRegen => Marshal.SizeOf(typeof(SmartAction.SetHealthRegen)),
|
||||||
|
SmartActions.SetRoot => Marshal.SizeOf(typeof(SmartAction.SetRoot)),
|
||||||
|
SmartActions.SetGoFlag => Marshal.SizeOf(typeof(SmartAction.Flag)),
|
||||||
|
SmartActions.AddGoFlag => Marshal.SizeOf(typeof(SmartAction.Flag)),
|
||||||
|
SmartActions.RemoveGoFlag => Marshal.SizeOf(typeof(SmartAction.Flag)),
|
||||||
|
SmartActions.SummonCreatureGroup => Marshal.SizeOf(typeof(SmartAction.CreatureGroup)),
|
||||||
|
SmartActions.SetPower => Marshal.SizeOf(typeof(SmartAction.Power)),
|
||||||
|
SmartActions.AddPower => Marshal.SizeOf(typeof(SmartAction.Power)),
|
||||||
|
SmartActions.RemovePower => Marshal.SizeOf(typeof(SmartAction.Power)),
|
||||||
|
SmartActions.GameEventStop => Marshal.SizeOf(typeof(SmartAction.GameEventStop)),
|
||||||
|
SmartActions.GameEventStart => Marshal.SizeOf(typeof(SmartAction.GameEventStart)),
|
||||||
|
SmartActions.StartClosestWaypoint => Marshal.SizeOf(typeof(SmartAction.ClosestWaypointFromList)),
|
||||||
|
SmartActions.MoveOffset => 0,
|
||||||
|
SmartActions.RandomSound => Marshal.SizeOf(typeof(SmartAction.RandomSound)),
|
||||||
|
SmartActions.SetCorpseDelay => Marshal.SizeOf(typeof(SmartAction.CorpseDelay)),
|
||||||
|
SmartActions.DisableEvade => Marshal.SizeOf(typeof(SmartAction.DisableEvade)),
|
||||||
|
SmartActions.GoSetGoState => Marshal.SizeOf(typeof(SmartAction.GoState)),
|
||||||
|
SmartActions.SetCanFly => Marshal.SizeOf(typeof(SmartAction.SetFly)),
|
||||||
|
SmartActions.RemoveAurasByType => Marshal.SizeOf(typeof(SmartAction.AuraType)),
|
||||||
|
SmartActions.SetSightDist => Marshal.SizeOf(typeof(SmartAction.SightDistance)),
|
||||||
|
SmartActions.Flee => Marshal.SizeOf(typeof(SmartAction.Flee)),
|
||||||
|
SmartActions.AddThreat => Marshal.SizeOf(typeof(SmartAction.Threat)),
|
||||||
|
SmartActions.LoadEquipment => Marshal.SizeOf(typeof(SmartAction.LoadEquipment)),
|
||||||
|
SmartActions.TriggerRandomTimedEvent => Marshal.SizeOf(typeof(SmartAction.RandomTimedEvent)),
|
||||||
|
SmartActions.RemoveAllGameobjects => 0,
|
||||||
|
SmartActions.PauseMovement => Marshal.SizeOf(typeof(SmartAction.PauseMovement)),
|
||||||
|
SmartActions.PlayAnimkit => Marshal.SizeOf(typeof(SmartAction.AnimKit)),
|
||||||
|
SmartActions.ScenePlay => Marshal.SizeOf(typeof(SmartAction.Scene)),
|
||||||
|
SmartActions.SceneCancel => Marshal.SizeOf(typeof(SmartAction.Scene)),
|
||||||
|
SmartActions.SpawnSpawngroup => Marshal.SizeOf(typeof(SmartAction.GroupSpawn)),
|
||||||
|
SmartActions.DespawnSpawngroup => Marshal.SizeOf(typeof(SmartAction.GroupSpawn)),
|
||||||
|
SmartActions.RespawnBySpawnId => Marshal.SizeOf(typeof(SmartAction.RespawnData)),
|
||||||
|
SmartActions.InvokerCast => Marshal.SizeOf(typeof(SmartAction.Cast)),
|
||||||
|
SmartActions.PlayCinematic => Marshal.SizeOf(typeof(SmartAction.Cinematic)),
|
||||||
|
SmartActions.SetMovementSpeed => Marshal.SizeOf(typeof(SmartAction.MovementSpeed)),
|
||||||
|
SmartActions.PlaySpellVisualKit => Marshal.SizeOf(typeof(SmartAction.SpellVisualKit)),
|
||||||
|
SmartActions.OverrideLight => Marshal.SizeOf(typeof(SmartAction.OverrideLight)),
|
||||||
|
SmartActions.OverrideWeather => Marshal.SizeOf(typeof(SmartAction.OverrideWeather)),
|
||||||
|
SmartActions.SetAIAnimKit => 0,
|
||||||
|
SmartActions.SetHover => Marshal.SizeOf(typeof(SmartAction.SetHover)),
|
||||||
|
SmartActions.SetHealthPct => Marshal.SizeOf(typeof(SmartAction.SetHealthPct)),
|
||||||
|
SmartActions.CreateConversation => Marshal.SizeOf(typeof(SmartAction.Conversation)),
|
||||||
|
//SmartActions.SetImmunePc => Marshal.SizeOf(typeof(SmartAction.Raw)),
|
||||||
|
//SmartActions.SetImmuneNpc => Marshal.SizeOf(typeof(SmartAction.Raw)),
|
||||||
|
//SmartActions.SetUninteractible => Marshal.SizeOf(typeof(SmartAction.Raw)),
|
||||||
|
//SmartActions.ActivateGameobject => Marshal.SizeOf(typeof(SmartAction.Raw)),
|
||||||
|
SmartActions.AddToStoredTargetList => Marshal.SizeOf(typeof(SmartAction.AddToStoredTargets)),
|
||||||
|
SmartActions.BecomePersonalCloneForPlayer => Marshal.SizeOf(typeof(SmartAction.BecomePersonalClone)),
|
||||||
|
_ => Marshal.SizeOf(typeof(SmartAction.Raw)),
|
||||||
|
};
|
||||||
|
|
||||||
|
int rawCount = Marshal.SizeOf(typeof(SmartAction.Raw)) / sizeof(uint);
|
||||||
|
int paramsCount = paramsStructSize / sizeof(uint);
|
||||||
|
|
||||||
|
bool valid = true;
|
||||||
|
for (int index = paramsCount; index < rawCount; index++)
|
||||||
|
{
|
||||||
|
uint value = 0;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
value = e.Action.raw.param1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
value = e.Action.raw.param2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
value = e.Action.raw.param3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
value = e.Action.raw.param4;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
value = e.Action.raw.param5;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
value = e.Action.raw.param6;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value != 0)
|
||||||
|
{
|
||||||
|
Log.outError(LogFilter.Sql, $"SmartAIMgr: {e} has unused action_param{index + 1} with value {value}, it must be 0, skipped.");
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CheckUnusedTargetParams(SmartScriptHolder e)
|
||||||
|
{
|
||||||
|
int paramsStructSize = e.Target.type switch
|
||||||
|
{
|
||||||
|
SmartTargets.None => 0,
|
||||||
|
SmartTargets.Self => 0,
|
||||||
|
SmartTargets.Victim => 0,
|
||||||
|
SmartTargets.HostileSecondAggro => Marshal.SizeOf(typeof(SmartTarget.HostilRandom)),
|
||||||
|
SmartTargets.HostileLastAggro => Marshal.SizeOf(typeof(SmartTarget.HostilRandom)),
|
||||||
|
SmartTargets.HostileRandom => Marshal.SizeOf(typeof(SmartTarget.HostilRandom)),
|
||||||
|
SmartTargets.HostileRandomNotTop => Marshal.SizeOf(typeof(SmartTarget.HostilRandom)),
|
||||||
|
SmartTargets.ActionInvoker => 0,
|
||||||
|
SmartTargets.Position => 0, //Uses X,Y,Z,O
|
||||||
|
SmartTargets.CreatureRange => Marshal.SizeOf(typeof(SmartTarget.UnitRange)),
|
||||||
|
SmartTargets.CreatureGuid => Marshal.SizeOf(typeof(SmartTarget.UnitGUID)),
|
||||||
|
SmartTargets.CreatureDistance => Marshal.SizeOf(typeof(SmartTarget.UnitDistance)),
|
||||||
|
SmartTargets.Stored => Marshal.SizeOf(typeof(SmartTarget.Stored)),
|
||||||
|
SmartTargets.GameobjectRange => Marshal.SizeOf(typeof(SmartTarget.GoRange)),
|
||||||
|
SmartTargets.GameobjectGuid => Marshal.SizeOf(typeof(SmartTarget.GoGUID)),
|
||||||
|
SmartTargets.GameobjectDistance => Marshal.SizeOf(typeof(SmartTarget.GoDistance)),
|
||||||
|
SmartTargets.InvokerParty => 0,
|
||||||
|
SmartTargets.PlayerRange => Marshal.SizeOf(typeof(SmartTarget.PlayerRange)),
|
||||||
|
SmartTargets.PlayerDistance => Marshal.SizeOf(typeof(SmartTarget.PlayerDistance)),
|
||||||
|
SmartTargets.ClosestCreature => Marshal.SizeOf(typeof(SmartTarget.UnitClosest)),
|
||||||
|
SmartTargets.ClosestGameobject => Marshal.SizeOf(typeof(SmartTarget.GoClosest)),
|
||||||
|
SmartTargets.ClosestPlayer => Marshal.SizeOf(typeof(SmartTarget.PlayerDistance)),
|
||||||
|
SmartTargets.ActionInvokerVehicle => 0,
|
||||||
|
SmartTargets.OwnerOrSummoner => Marshal.SizeOf(typeof(SmartTarget.Owner)),
|
||||||
|
SmartTargets.ThreatList => Marshal.SizeOf(typeof(SmartTarget.ThreatList)),
|
||||||
|
SmartTargets.ClosestEnemy => Marshal.SizeOf(typeof(SmartTarget.ClosestAttackable)),
|
||||||
|
SmartTargets.ClosestFriendly => Marshal.SizeOf(typeof(SmartTarget.ClosestFriendly)),
|
||||||
|
SmartTargets.LootRecipients => 0,
|
||||||
|
SmartTargets.Farthest => Marshal.SizeOf(typeof(SmartTarget.Farthest)),
|
||||||
|
SmartTargets.VehiclePassenger => Marshal.SizeOf(typeof(SmartTarget.Vehicle)),
|
||||||
|
SmartTargets.ClosestUnspawnedGameobject => Marshal.SizeOf(typeof(SmartTarget.GoClosest)),
|
||||||
|
_ => Marshal.SizeOf(typeof(SmartTarget.Raw)),
|
||||||
|
};
|
||||||
|
|
||||||
|
int rawCount = Marshal.SizeOf(typeof(SmartTarget.Raw)) / sizeof(uint);
|
||||||
|
int paramsCount = paramsStructSize / sizeof(uint);
|
||||||
|
|
||||||
|
bool valid = true;
|
||||||
|
for (int index = paramsCount; index < rawCount; index++)
|
||||||
|
{
|
||||||
|
uint value = 0;
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
value = e.Target.raw.param1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
value = e.Target.raw.param2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
value = e.Target.raw.param3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
value = e.Target.raw.param4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (value != 0)
|
||||||
|
{
|
||||||
|
Log.outError(LogFilter.Sql, $"SmartAIMgr: {e} has unused target_param{index + 1} with value {value}, it must be 0, skipped.");
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsEventValid(SmartScriptHolder e)
|
bool IsEventValid(SmartScriptHolder e)
|
||||||
{
|
{
|
||||||
if (e.Event.type >= SmartEvents.End)
|
if (e.Event.type >= SmartEvents.End)
|
||||||
@@ -984,21 +1380,29 @@ namespace Game.AI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!CheckUnusedEventParams(e))
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (e.GetActionType())
|
switch (e.GetActionType())
|
||||||
{
|
{
|
||||||
case SmartActions.Talk:
|
case SmartActions.Talk:
|
||||||
TC_SAI_IS_BOOLEAN_VALID(e, e.Action.talk.useTalkTarget);
|
|
||||||
goto case SmartActions.SimpleTalk;
|
|
||||||
case SmartActions.SimpleTalk:
|
|
||||||
{
|
{
|
||||||
|
TC_SAI_IS_BOOLEAN_VALID(e, e.Action.talk.useTalkTarget);
|
||||||
|
|
||||||
if (!IsTextValid(e, e.Action.talk.textGroupId))
|
if (!IsTextValid(e, e.Action.talk.textGroupId))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SmartActions.SimpleTalk:
|
||||||
|
{
|
||||||
|
if (!IsTextValid(e, e.Action.simpleTalk.textGroupId))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SmartActions.SetFaction:
|
case SmartActions.SetFaction:
|
||||||
if (e.Action.faction.factionID != 0 && CliDB.FactionTemplateStorage.LookupByKey(e.Action.faction.factionID) == null)
|
if (e.Action.faction.factionId != 0 && CliDB.FactionTemplateStorage.LookupByKey(e.Action.faction.factionId) == null)
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.ScriptsAi, $"SmartAIMgr: {e} uses non-existent Faction {e.Action.faction.factionID}, skipped.");
|
Log.outError(LogFilter.ScriptsAi, $"SmartAIMgr: {e} uses non-existent Faction {e.Action.faction.factionId}, skipped.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1132,6 +1536,10 @@ namespace Game.AI
|
|||||||
if (!IsSpellValid(e, e.Action.cast.spell))
|
if (!IsSpellValid(e, e.Action.cast.spell))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
case SmartActions.AddAura:
|
||||||
|
if (!IsSpellValid(e, e.Action.addAura.spell))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
case SmartActions.CallAreaexploredoreventhappens:
|
case SmartActions.CallAreaexploredoreventhappens:
|
||||||
case SmartActions.CallGroupeventhappens:
|
case SmartActions.CallGroupeventhappens:
|
||||||
Quest qid = Global.ObjectMgr.GetQuestTemplate(e.Action.quest.questId);
|
Quest qid = Global.ObjectMgr.GetQuestTemplate(e.Action.quest.questId);
|
||||||
@@ -1316,7 +1724,7 @@ namespace Game.AI
|
|||||||
}
|
}
|
||||||
case SmartActions.CallRandomRangeTimedActionlist:
|
case SmartActions.CallRandomRangeTimedActionlist:
|
||||||
{
|
{
|
||||||
if (!IsMinMaxValid(e, e.Action.randTimedActionList.actionList1, e.Action.randTimedActionList.actionList2))
|
if (!IsMinMaxValid(e, e.Action.randRangeTimedActionList.idMin, e.Action.randRangeTimedActionList.idMax))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1675,6 +2083,11 @@ namespace Game.AI
|
|||||||
TC_SAI_IS_BOOLEAN_VALID(e, e.Action.evade.toRespawnPosition);
|
TC_SAI_IS_BOOLEAN_VALID(e, e.Action.evade.toRespawnPosition);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SmartActions.SetHealthRegen:
|
||||||
|
{
|
||||||
|
TC_SAI_IS_BOOLEAN_VALID(e, e.Action.setHealthRegen.regenHealth);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SmartActions.CreateConversation:
|
case SmartActions.CreateConversation:
|
||||||
{
|
{
|
||||||
if (Global.ConversationDataStorage.GetConversationTemplate(e.Action.conversation.id) == null)
|
if (Global.ConversationDataStorage.GetConversationTemplate(e.Action.conversation.id) == null)
|
||||||
@@ -1732,7 +2145,6 @@ namespace Game.AI
|
|||||||
case SmartActions.GoSetGoState:
|
case SmartActions.GoSetGoState:
|
||||||
case SmartActions.SendTargetToTarget:
|
case SmartActions.SendTargetToTarget:
|
||||||
case SmartActions.SetHomePos:
|
case SmartActions.SetHomePos:
|
||||||
case SmartActions.SetHealthRegen:
|
|
||||||
case SmartActions.SetGoFlag:
|
case SmartActions.SetGoFlag:
|
||||||
case SmartActions.AddGoFlag:
|
case SmartActions.AddGoFlag:
|
||||||
case SmartActions.RemoveGoFlag:
|
case SmartActions.RemoveGoFlag:
|
||||||
@@ -1761,8 +2173,12 @@ namespace Game.AI
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!CheckUnusedActionParams(e))
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsAnimKitValid(SmartScriptHolder e, uint entry)
|
static bool IsAnimKitValid(SmartScriptHolder e, uint entry)
|
||||||
{
|
{
|
||||||
if (!CliDB.AnimKitStorage.ContainsKey(entry))
|
if (!CliDB.AnimKitStorage.ContainsKey(entry))
|
||||||
@@ -2168,7 +2584,7 @@ namespace Game.AI
|
|||||||
public TargetCasting targetCasting;
|
public TargetCasting targetCasting;
|
||||||
|
|
||||||
[FieldOffset(16)]
|
[FieldOffset(16)]
|
||||||
public FriendlyHealt friendlyHealth;
|
public FriendlyHealth friendlyHealth;
|
||||||
|
|
||||||
[FieldOffset(16)]
|
[FieldOffset(16)]
|
||||||
public FriendlyCC friendlyCC;
|
public FriendlyCC friendlyCC;
|
||||||
@@ -2194,9 +2610,6 @@ namespace Game.AI
|
|||||||
[FieldOffset(16)]
|
[FieldOffset(16)]
|
||||||
public Charm charm;
|
public Charm charm;
|
||||||
|
|
||||||
[FieldOffset(16)]
|
|
||||||
public TargetAura targetAura;
|
|
||||||
|
|
||||||
[FieldOffset(16)]
|
[FieldOffset(16)]
|
||||||
public MovementInform movementInform;
|
public MovementInform movementInform;
|
||||||
|
|
||||||
@@ -2230,9 +2643,6 @@ namespace Game.AI
|
|||||||
[FieldOffset(16)]
|
[FieldOffset(16)]
|
||||||
public Gossip gossip;
|
public Gossip gossip;
|
||||||
|
|
||||||
[FieldOffset(16)]
|
|
||||||
public Dummy dummy;
|
|
||||||
|
|
||||||
[FieldOffset(16)]
|
[FieldOffset(16)]
|
||||||
public EventPhaseChange eventPhaseChange;
|
public EventPhaseChange eventPhaseChange;
|
||||||
|
|
||||||
@@ -2260,9 +2670,6 @@ namespace Game.AI
|
|||||||
[FieldOffset(16)]
|
[FieldOffset(16)]
|
||||||
public Counter counter;
|
public Counter counter;
|
||||||
|
|
||||||
[FieldOffset(16)]
|
|
||||||
public Scene scene;
|
|
||||||
|
|
||||||
[FieldOffset(16)]
|
[FieldOffset(16)]
|
||||||
public Spell spell;
|
public Spell spell;
|
||||||
|
|
||||||
@@ -2319,7 +2726,7 @@ namespace Game.AI
|
|||||||
public uint repeatMax;
|
public uint repeatMax;
|
||||||
public uint spellId;
|
public uint spellId;
|
||||||
}
|
}
|
||||||
public struct FriendlyHealt
|
public struct FriendlyHealth
|
||||||
{
|
{
|
||||||
public uint hpDeficit;
|
public uint hpDeficit;
|
||||||
public uint radius;
|
public uint radius;
|
||||||
@@ -2372,13 +2779,6 @@ namespace Game.AI
|
|||||||
{
|
{
|
||||||
public uint onRemove;
|
public uint onRemove;
|
||||||
}
|
}
|
||||||
public struct TargetAura
|
|
||||||
{
|
|
||||||
public uint spell;
|
|
||||||
public uint count;
|
|
||||||
public uint repeatMin;
|
|
||||||
public uint repeatMax;
|
|
||||||
}
|
|
||||||
public struct MovementInform
|
public struct MovementInform
|
||||||
{
|
{
|
||||||
public uint type;
|
public uint type;
|
||||||
@@ -2432,11 +2832,6 @@ namespace Game.AI
|
|||||||
public uint sender;
|
public uint sender;
|
||||||
public uint action;
|
public uint action;
|
||||||
}
|
}
|
||||||
public struct Dummy
|
|
||||||
{
|
|
||||||
public uint spell;
|
|
||||||
public uint effIndex;
|
|
||||||
}
|
|
||||||
public struct EventPhaseChange
|
public struct EventPhaseChange
|
||||||
{
|
{
|
||||||
public uint phasemask;
|
public uint phasemask;
|
||||||
@@ -2484,10 +2879,6 @@ namespace Game.AI
|
|||||||
public uint cooldownMin;
|
public uint cooldownMin;
|
||||||
public uint cooldownMax;
|
public uint cooldownMax;
|
||||||
}
|
}
|
||||||
public struct Scene
|
|
||||||
{
|
|
||||||
public uint sceneId;
|
|
||||||
}
|
|
||||||
public struct Spell
|
public struct Spell
|
||||||
{
|
{
|
||||||
public uint effIndex;
|
public uint effIndex;
|
||||||
@@ -2512,6 +2903,9 @@ namespace Game.AI
|
|||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public Talk talk;
|
public Talk talk;
|
||||||
|
|
||||||
|
[FieldOffset(4)]
|
||||||
|
public SimpleTalk simpleTalk;
|
||||||
|
|
||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public Faction faction;
|
public Faction faction;
|
||||||
|
|
||||||
@@ -2548,15 +2942,12 @@ namespace Game.AI
|
|||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public ThreatPCT threatPCT;
|
public ThreatPCT threatPCT;
|
||||||
|
|
||||||
|
[FieldOffset(4)]
|
||||||
|
public Threat threat;
|
||||||
|
|
||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public CastCreatureOrGO castCreatureOrGO;
|
public CastCreatureOrGO castCreatureOrGO;
|
||||||
|
|
||||||
[FieldOffset(4)]
|
|
||||||
public AddUnitFlag addUnitFlag;
|
|
||||||
|
|
||||||
[FieldOffset(4)]
|
|
||||||
public RemoveUnitFlag removeUnitFlag;
|
|
||||||
|
|
||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public AutoAttack autoAttack;
|
public AutoAttack autoAttack;
|
||||||
|
|
||||||
@@ -2569,6 +2960,9 @@ namespace Game.AI
|
|||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public IncEventPhase incEventPhase;
|
public IncEventPhase incEventPhase;
|
||||||
|
|
||||||
|
[FieldOffset(4)]
|
||||||
|
public AddAura addAura;
|
||||||
|
|
||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public CastedCreatureOrGO castedCreatureOrGO;
|
public CastedCreatureOrGO castedCreatureOrGO;
|
||||||
|
|
||||||
@@ -2665,9 +3059,6 @@ namespace Game.AI
|
|||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public SetCounter setCounter;
|
public SetCounter setCounter;
|
||||||
|
|
||||||
[FieldOffset(4)]
|
|
||||||
public StoreVar storeVar;
|
|
||||||
|
|
||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public StoreTargets storeTargets;
|
public StoreTargets storeTargets;
|
||||||
|
|
||||||
@@ -2683,21 +3074,24 @@ namespace Game.AI
|
|||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public UnitFlag unitFlag;
|
public UnitFlag unitFlag;
|
||||||
|
|
||||||
|
[FieldOffset(4)]
|
||||||
|
public Flag flag;
|
||||||
|
|
||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public SetunitByte setunitByte;
|
public SetunitByte setunitByte;
|
||||||
|
|
||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public DelunitByte delunitByte;
|
public DelunitByte delunitByte;
|
||||||
|
|
||||||
[FieldOffset(4)]
|
|
||||||
public EnterVehicle enterVehicle;
|
|
||||||
|
|
||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public TimedActionList timedActionList;
|
public TimedActionList timedActionList;
|
||||||
|
|
||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public RandTimedActionList randTimedActionList;
|
public RandTimedActionList randTimedActionList;
|
||||||
|
|
||||||
|
[FieldOffset(4)]
|
||||||
|
public RandRangeTimedActionList randRangeTimedActionList;
|
||||||
|
|
||||||
[FieldOffset(4)]
|
[FieldOffset(4)]
|
||||||
public InterruptSpellCasting interruptSpellCasting;
|
public InterruptSpellCasting interruptSpellCasting;
|
||||||
|
|
||||||
@@ -2834,9 +3228,14 @@ namespace Game.AI
|
|||||||
public uint duration;
|
public uint duration;
|
||||||
public uint useTalkTarget;
|
public uint useTalkTarget;
|
||||||
}
|
}
|
||||||
|
public struct SimpleTalk
|
||||||
|
{
|
||||||
|
public uint textGroupId;
|
||||||
|
public uint duration;
|
||||||
|
}
|
||||||
public struct Faction
|
public struct Faction
|
||||||
{
|
{
|
||||||
public uint factionID;
|
public uint factionId;
|
||||||
}
|
}
|
||||||
public struct MorphOrMount
|
public struct MorphOrMount
|
||||||
{
|
{
|
||||||
@@ -2912,23 +3311,10 @@ namespace Game.AI
|
|||||||
public uint quest;
|
public uint quest;
|
||||||
public uint spell;
|
public uint spell;
|
||||||
}
|
}
|
||||||
public struct AddUnitFlag
|
public struct Threat
|
||||||
{
|
{
|
||||||
public uint flag1;
|
public uint threatINC;
|
||||||
public uint flag2;
|
public uint threatDEC;
|
||||||
public uint flag3;
|
|
||||||
public uint flag4;
|
|
||||||
public uint flag5;
|
|
||||||
public uint flag6;
|
|
||||||
}
|
|
||||||
public struct RemoveUnitFlag
|
|
||||||
{
|
|
||||||
public uint flag1;
|
|
||||||
public uint flag2;
|
|
||||||
public uint flag3;
|
|
||||||
public uint flag4;
|
|
||||||
public uint flag5;
|
|
||||||
public uint flag6;
|
|
||||||
}
|
}
|
||||||
public struct AutoAttack
|
public struct AutoAttack
|
||||||
{
|
{
|
||||||
@@ -2947,6 +3333,10 @@ namespace Game.AI
|
|||||||
public uint inc;
|
public uint inc;
|
||||||
public uint dec;
|
public uint dec;
|
||||||
}
|
}
|
||||||
|
public struct AddAura
|
||||||
|
{
|
||||||
|
public uint spell;
|
||||||
|
}
|
||||||
public struct CastedCreatureOrGO
|
public struct CastedCreatureOrGO
|
||||||
{
|
{
|
||||||
public uint creature;
|
public uint creature;
|
||||||
@@ -3114,11 +3504,6 @@ namespace Game.AI
|
|||||||
public uint value;
|
public uint value;
|
||||||
public uint reset;
|
public uint reset;
|
||||||
}
|
}
|
||||||
public struct StoreVar
|
|
||||||
{
|
|
||||||
public uint id;
|
|
||||||
public uint number;
|
|
||||||
}
|
|
||||||
public struct StoreTargets
|
public struct StoreTargets
|
||||||
{
|
{
|
||||||
public uint id;
|
public uint id;
|
||||||
@@ -3149,6 +3534,10 @@ namespace Game.AI
|
|||||||
public uint flag;
|
public uint flag;
|
||||||
public uint type;
|
public uint type;
|
||||||
}
|
}
|
||||||
|
public struct Flag
|
||||||
|
{
|
||||||
|
public uint flag;
|
||||||
|
}
|
||||||
public struct SetunitByte
|
public struct SetunitByte
|
||||||
{
|
{
|
||||||
public uint byte1;
|
public uint byte1;
|
||||||
@@ -3159,10 +3548,6 @@ namespace Game.AI
|
|||||||
public uint byte1;
|
public uint byte1;
|
||||||
public uint type;
|
public uint type;
|
||||||
}
|
}
|
||||||
public struct EnterVehicle
|
|
||||||
{
|
|
||||||
public uint seat;
|
|
||||||
}
|
|
||||||
public struct TimedActionList
|
public struct TimedActionList
|
||||||
{
|
{
|
||||||
public uint id;
|
public uint id;
|
||||||
@@ -3178,6 +3563,11 @@ namespace Game.AI
|
|||||||
public uint actionList5;
|
public uint actionList5;
|
||||||
public uint actionList6;
|
public uint actionList6;
|
||||||
}
|
}
|
||||||
|
public struct RandRangeTimedActionList
|
||||||
|
{
|
||||||
|
public uint idMin;
|
||||||
|
public uint idMax;
|
||||||
|
}
|
||||||
public struct InterruptSpellCasting
|
public struct InterruptSpellCasting
|
||||||
{
|
{
|
||||||
public uint withDelayed;
|
public uint withDelayed;
|
||||||
@@ -3450,10 +3840,10 @@ namespace Game.AI
|
|||||||
public GoDistance goDistance;
|
public GoDistance goDistance;
|
||||||
|
|
||||||
[FieldOffset(20)]
|
[FieldOffset(20)]
|
||||||
public Position postion;
|
public UnitClosest unitClosest;
|
||||||
|
|
||||||
[FieldOffset(20)]
|
[FieldOffset(20)]
|
||||||
public Closest closest;
|
public GoClosest goClosest;
|
||||||
|
|
||||||
[FieldOffset(20)]
|
[FieldOffset(20)]
|
||||||
public ClosestAttackable closestAttackable;
|
public ClosestAttackable closestAttackable;
|
||||||
@@ -3467,6 +3857,9 @@ namespace Game.AI
|
|||||||
[FieldOffset(20)]
|
[FieldOffset(20)]
|
||||||
public Vehicle vehicle;
|
public Vehicle vehicle;
|
||||||
|
|
||||||
|
[FieldOffset(20)]
|
||||||
|
public ThreatList threatList;
|
||||||
|
|
||||||
[FieldOffset(20)]
|
[FieldOffset(20)]
|
||||||
public Raw raw;
|
public Raw raw;
|
||||||
|
|
||||||
@@ -3532,16 +3925,17 @@ namespace Game.AI
|
|||||||
public uint dist;
|
public uint dist;
|
||||||
public uint maxSize;
|
public uint maxSize;
|
||||||
}
|
}
|
||||||
public struct Position
|
public struct UnitClosest
|
||||||
{
|
|
||||||
public uint map;
|
|
||||||
}
|
|
||||||
public struct Closest
|
|
||||||
{
|
{
|
||||||
public uint entry;
|
public uint entry;
|
||||||
public uint dist;
|
public uint dist;
|
||||||
public uint dead;
|
public uint dead;
|
||||||
}
|
}
|
||||||
|
public struct GoClosest
|
||||||
|
{
|
||||||
|
public uint entry;
|
||||||
|
public uint dist;
|
||||||
|
}
|
||||||
public struct ClosestAttackable
|
public struct ClosestAttackable
|
||||||
{
|
{
|
||||||
public uint maxDist;
|
public uint maxDist;
|
||||||
@@ -3560,6 +3954,10 @@ namespace Game.AI
|
|||||||
{
|
{
|
||||||
public uint seatMask;
|
public uint seatMask;
|
||||||
}
|
}
|
||||||
|
public struct ThreatList
|
||||||
|
{
|
||||||
|
public uint maxDist;
|
||||||
|
}
|
||||||
public struct Raw
|
public struct Raw
|
||||||
{
|
{
|
||||||
public uint param1;
|
public uint param1;
|
||||||
|
|||||||
@@ -212,14 +212,14 @@ namespace Game.AI
|
|||||||
foreach (var target in targets)
|
foreach (var target in targets)
|
||||||
{
|
{
|
||||||
if (IsCreature(target))
|
if (IsCreature(target))
|
||||||
Global.CreatureTextMgr.SendChat(target.ToCreature(), (byte)e.Action.talk.textGroupId, IsPlayer(GetLastInvoker()) ? GetLastInvoker() : null);
|
Global.CreatureTextMgr.SendChat(target.ToCreature(), (byte)e.Action.simpleTalk.textGroupId, IsPlayer(GetLastInvoker()) ? GetLastInvoker() : null);
|
||||||
else if (IsPlayer(target) && _me != null)
|
else if (IsPlayer(target) && _me != null)
|
||||||
{
|
{
|
||||||
Unit templastInvoker = GetLastInvoker();
|
Unit templastInvoker = GetLastInvoker();
|
||||||
Global.CreatureTextMgr.SendChat(_me, (byte)e.Action.talk.textGroupId, IsPlayer(templastInvoker) ? templastInvoker : null, ChatMsg.Addon, Language.Addon, CreatureTextRange.Normal, 0, SoundKitPlayType.Normal, Team.Other, false, target.ToPlayer());
|
Global.CreatureTextMgr.SendChat(_me, (byte)e.Action.simpleTalk.textGroupId, IsPlayer(templastInvoker) ? templastInvoker : null, ChatMsg.Addon, Language.Addon, CreatureTextRange.Normal, 0, SoundKitPlayType.Normal, Team.Other, false, target.ToPlayer());
|
||||||
}
|
}
|
||||||
Log.outDebug(LogFilter.ScriptsAi, "SmartScript.ProcessAction. SMART_ACTION_SIMPLE_TALK: talker: {0} (GuidLow: {1}), textGroupId: {2}",
|
Log.outDebug(LogFilter.ScriptsAi, "SmartScript.ProcessAction. SMART_ACTION_SIMPLE_TALK: talker: {0} (GuidLow: {1}), textGroupId: {2}",
|
||||||
target.GetName(), target.GetGUID().ToString(), e.Action.talk.textGroupId);
|
target.GetName(), target.GetGUID().ToString(), e.Action.simpleTalk.textGroupId);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -259,11 +259,11 @@ namespace Game.AI
|
|||||||
{
|
{
|
||||||
if (IsCreature(target))
|
if (IsCreature(target))
|
||||||
{
|
{
|
||||||
if (e.Action.faction.factionID != 0)
|
if (e.Action.faction.factionId != 0)
|
||||||
{
|
{
|
||||||
target.ToCreature().SetFaction(e.Action.faction.factionID);
|
target.ToCreature().SetFaction(e.Action.faction.factionId);
|
||||||
Log.outDebug(LogFilter.ScriptsAi, "SmartScript.ProcessAction. SMART_ACTION_SET_FACTION: Creature entry {0}, GuidLow {1} set faction to {2}",
|
Log.outDebug(LogFilter.ScriptsAi, "SmartScript.ProcessAction. SMART_ACTION_SET_FACTION: Creature entry {0}, GuidLow {1} set faction to {2}",
|
||||||
target.GetEntry(), target.GetGUID().ToString(), e.Action.faction.factionID);
|
target.GetEntry(), target.GetGUID().ToString(), e.Action.faction.factionId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1681,21 +1681,21 @@ namespace Game.AI
|
|||||||
{
|
{
|
||||||
foreach (var target in targets)
|
foreach (var target in targets)
|
||||||
if (IsUnit(target))
|
if (IsUnit(target))
|
||||||
target.ToUnit().SetNpcFlags((NPCFlags)e.Action.unitFlag.flag);
|
target.ToUnit().SetNpcFlags((NPCFlags)e.Action.flag.flag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SmartActions.AddNpcFlag:
|
case SmartActions.AddNpcFlag:
|
||||||
{
|
{
|
||||||
foreach (var target in targets)
|
foreach (var target in targets)
|
||||||
if (IsUnit(target))
|
if (IsUnit(target))
|
||||||
target.ToUnit().AddNpcFlag((NPCFlags)e.Action.unitFlag.flag);
|
target.ToUnit().AddNpcFlag((NPCFlags)e.Action.flag.flag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SmartActions.RemoveNpcFlag:
|
case SmartActions.RemoveNpcFlag:
|
||||||
{
|
{
|
||||||
foreach (var target in targets)
|
foreach (var target in targets)
|
||||||
if (IsUnit(target))
|
if (IsUnit(target))
|
||||||
target.ToUnit().RemoveNpcFlag((NPCFlags)e.Action.unitFlag.flag);
|
target.ToUnit().RemoveNpcFlag((NPCFlags)e.Action.flag.flag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SmartActions.CrossCast:
|
case SmartActions.CrossCast:
|
||||||
@@ -1780,7 +1780,7 @@ namespace Game.AI
|
|||||||
}
|
}
|
||||||
case SmartActions.CallRandomRangeTimedActionlist:
|
case SmartActions.CallRandomRangeTimedActionlist:
|
||||||
{
|
{
|
||||||
uint id = 0;// RandomHelper.URand(e.Action.randTimedActionList.actionLists[0], e.Action.randTimedActionList.actionLists[1]);
|
uint id = RandomHelper.URand(e.Action.randRangeTimedActionList.idMin, e.Action.randRangeTimedActionList.idMax);
|
||||||
if (e.GetTargetType() == SmartTargets.None)
|
if (e.GetTargetType() == SmartTargets.None)
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Sql, "SmartScript: Entry {0} SourceType {1} Event {2} Action {3} is using TARGET_NONE(0) for Script9 target. Please correct target_type in database.", e.EntryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType());
|
Log.outError(LogFilter.Sql, "SmartScript: Entry {0} SourceType {1} Event {2} Action {3} is using TARGET_NONE(0) for Script9 target. Please correct target_type in database.", e.EntryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType());
|
||||||
@@ -1916,21 +1916,21 @@ namespace Game.AI
|
|||||||
{
|
{
|
||||||
foreach (var target in targets)
|
foreach (var target in targets)
|
||||||
if (IsUnit(target))
|
if (IsUnit(target))
|
||||||
target.ToUnit().SetDynamicFlags((UnitDynFlags)e.Action.unitFlag.flag);
|
target.ToUnit().SetDynamicFlags((UnitDynFlags)e.Action.flag.flag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SmartActions.AddDynamicFlag:
|
case SmartActions.AddDynamicFlag:
|
||||||
{
|
{
|
||||||
foreach (var target in targets)
|
foreach (var target in targets)
|
||||||
if (IsUnit(target))
|
if (IsUnit(target))
|
||||||
target.ToUnit().AddDynamicFlag((UnitDynFlags)e.Action.unitFlag.flag);
|
target.ToUnit().AddDynamicFlag((UnitDynFlags)e.Action.flag.flag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SmartActions.RemoveDynamicFlag:
|
case SmartActions.RemoveDynamicFlag:
|
||||||
{
|
{
|
||||||
foreach (var target in targets)
|
foreach (var target in targets)
|
||||||
if (IsUnit(target))
|
if (IsUnit(target))
|
||||||
target.ToUnit().RemoveDynamicFlag((UnitDynFlags)e.Action.unitFlag.flag);
|
target.ToUnit().RemoveDynamicFlag((UnitDynFlags)e.Action.flag.flag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SmartActions.JumpToPos:
|
case SmartActions.JumpToPos:
|
||||||
@@ -2313,7 +2313,7 @@ namespace Game.AI
|
|||||||
|
|
||||||
foreach (var target in targets)
|
foreach (var target in targets)
|
||||||
if (IsUnit(target))
|
if (IsUnit(target))
|
||||||
_me.GetThreatManager().AddThreat(target.ToUnit(), (float)(e.Action.threatPCT.threatINC - (float)e.Action.threatPCT.threatDEC), null, true, true);
|
_me.GetThreatManager().AddThreat(target.ToUnit(), (float)(e.Action.threat.threatINC - (float)e.Action.threat.threatDEC), null, true, true);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3000,7 +3000,7 @@ namespace Game.AI
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Creature target = refObj.FindNearestCreature(e.Target.closest.entry, e.Target.closest.dist != 0 ? e.Target.closest.dist : 100, e.Target.closest.dead == 0);
|
Creature target = refObj.FindNearestCreature(e.Target.unitClosest.entry, e.Target.unitClosest.dist != 0 ? e.Target.unitClosest.dist : 100, e.Target.unitClosest.dead == 0);
|
||||||
if (target)
|
if (target)
|
||||||
targets.Add(target);
|
targets.Add(target);
|
||||||
break;
|
break;
|
||||||
@@ -3017,7 +3017,7 @@ namespace Game.AI
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObject target = refObj.FindNearestGameObject(e.Target.closest.entry, e.Target.closest.dist != 0 ? e.Target.closest.dist : 100);
|
GameObject target = refObj.FindNearestGameObject(e.Target.goClosest.entry, e.Target.goClosest.dist != 0 ? e.Target.goClosest.dist : 100);
|
||||||
if (target)
|
if (target)
|
||||||
targets.Add(target);
|
targets.Add(target);
|
||||||
break;
|
break;
|
||||||
@@ -3086,7 +3086,7 @@ namespace Game.AI
|
|||||||
if (_me != null && _me.CanHaveThreatList())
|
if (_me != null && _me.CanHaveThreatList())
|
||||||
{
|
{
|
||||||
foreach (var refe in _me.GetThreatManager().GetSortedThreatList())
|
foreach (var refe in _me.GetThreatManager().GetSortedThreatList())
|
||||||
if (e.Target.hostilRandom.maxDist == 0 || _me.IsWithinCombatRange(refe.GetVictim(), e.Target.hostilRandom.maxDist))
|
if (e.Target.threatList.maxDist == 0 || _me.IsWithinCombatRange(refe.GetVictim(), e.Target.threatList.maxDist))
|
||||||
targets.Add(refe.GetVictim());
|
targets.Add(refe.GetVictim());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -3154,7 +3154,7 @@ namespace Game.AI
|
|||||||
}
|
}
|
||||||
case SmartTargets.ClosestUnspawnedGameobject:
|
case SmartTargets.ClosestUnspawnedGameobject:
|
||||||
{
|
{
|
||||||
GameObject target = baseObject.FindNearestUnspawnedGameObject(e.Target.closest.entry, (float)(e.Target.closest.dist != 0 ? e.Target.closest.dist : 100));
|
GameObject target = baseObject.FindNearestUnspawnedGameObject(e.Target.goClosest.entry, (float)(e.Target.goClosest.dist != 0 ? e.Target.goClosest.dist : 100));
|
||||||
if (target != null)
|
if (target != null)
|
||||||
targets.Add(target);
|
targets.Add(target);
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user