Core/Auras: Implemented mount equipment

Port From (https://github.com/TrinityCore/TrinityCore/commit/6dd5fb9d88e7a8b7da696bbe7b96947217b1ace2)
This commit is contained in:
Hondacrx
2025-02-17 15:06:19 -05:00
parent f3b2f98c78
commit 4d2dbbcf16
8 changed files with 154 additions and 7 deletions
+13 -5
View File
@@ -1889,11 +1889,19 @@ namespace Framework.Constants
public enum MountFlags : int public enum MountFlags : int
{ {
SelfMount = 0x02, // Player becomes the mount himself ServerOnly = 0x01,
FactionSpecific = 0x04, IsSelfMount = 0x02,
PreferredSwimming = 0x10, ExcludeFromJournalIfFactionDoesntMatch = 0x04,
PreferredWaterWalking = 0x20, AllowMountedCombat = 0x08,
HideIfUnknown = 0x40 SummonRandomFavorWhileUnderwater = 0x10,
SummonRandomFavorWhileAtWaterSurface = 0x20,
ExcludeFromJournalIfNotLearned = 0x40,
SummonRandomDoNotFavorWhenGrounded = 0x80,
ShowInSpellbook = 0x100,
AddToActionBarOnLearn = 0x200,
NotForUseAsATaxi = 0x400,
MountEquipmentEffectsSuppressed = 0x800,
DisablePlayerMountPreview = 0x1000,
} }
public enum PathPropertyIndex public enum PathPropertyIndex
@@ -962,6 +962,10 @@ namespace Framework.Database
PrepareStatement(HotfixStatements.SEL_MOUNT_CAPABILITY, "SELECT ID, Flags, ReqRidingSkill, ReqAreaID, ReqSpellAuraID, ReqSpellKnownID, ModSpellAuraID, " + PrepareStatement(HotfixStatements.SEL_MOUNT_CAPABILITY, "SELECT ID, Flags, ReqRidingSkill, ReqAreaID, ReqSpellAuraID, ReqSpellKnownID, ModSpellAuraID, " +
"ReqMapID, PlayerConditionID, FlightCapabilityID FROM mount_capability WHERE (`VerifiedBuild` > 0) = ?"); "ReqMapID, PlayerConditionID, FlightCapabilityID FROM mount_capability WHERE (`VerifiedBuild` > 0) = ?");
// MountEquipment.db2
PrepareStatement(HotfixStatements.SEL_MOUNT_EQUIPMENT, "SELECT ID, Item, BuffSpell, Unknown820, LearnedBySpell FROM mount_equipment" +
" WHERE (`VerifiedBuild` > 0) = ?");
// MountTypeXCapability.db2 // MountTypeXCapability.db2
PrepareStatement(HotfixStatements.SEL_MOUNT_TYPE_X_CAPABILITY, "SELECT ID, MountTypeID, MountCapabilityID, OrderIndex FROM mount_type_x_capability" + PrepareStatement(HotfixStatements.SEL_MOUNT_TYPE_X_CAPABILITY, "SELECT ID, MountTypeID, MountCapabilityID, OrderIndex FROM mount_type_x_capability" +
" WHERE (`VerifiedBuild` > 0) = ?"); " WHERE (`VerifiedBuild` > 0) = ?");
@@ -2095,6 +2099,8 @@ namespace Framework.Database
SEL_MOUNT_CAPABILITY, SEL_MOUNT_CAPABILITY,
SEL_MOUNT_EQUIPMENT,
SEL_MOUNT_TYPE_X_CAPABILITY, SEL_MOUNT_TYPE_X_CAPABILITY,
SEL_MOUNT_X_DISPLAY, SEL_MOUNT_X_DISPLAY,
+2
View File
@@ -244,6 +244,7 @@ namespace Game.DataStorage
ModifierTreeStorage = ReadDB2<ModifierTreeRecord>("ModifierTree.db2", HotfixStatements.SEL_MODIFIER_TREE); ModifierTreeStorage = ReadDB2<ModifierTreeRecord>("ModifierTree.db2", HotfixStatements.SEL_MODIFIER_TREE);
MountCapabilityStorage = ReadDB2<MountCapabilityRecord>("MountCapability.db2", HotfixStatements.SEL_MOUNT_CAPABILITY); MountCapabilityStorage = ReadDB2<MountCapabilityRecord>("MountCapability.db2", HotfixStatements.SEL_MOUNT_CAPABILITY);
MountStorage = ReadDB2<MountRecord>("Mount.db2", HotfixStatements.SEL_MOUNT, HotfixStatements.SEL_MOUNT_LOCALE); MountStorage = ReadDB2<MountRecord>("Mount.db2", HotfixStatements.SEL_MOUNT, HotfixStatements.SEL_MOUNT_LOCALE);
MountEquipmentStorage = ReadDB2<MountEquipmentRecord>("MountEquipment.db2", HotfixStatements.SEL_MOUNT_EQUIPMENT);
MountTypeXCapabilityStorage = ReadDB2<MountTypeXCapabilityRecord>("MountTypeXCapability.db2", HotfixStatements.SEL_MOUNT_TYPE_X_CAPABILITY); MountTypeXCapabilityStorage = ReadDB2<MountTypeXCapabilityRecord>("MountTypeXCapability.db2", HotfixStatements.SEL_MOUNT_TYPE_X_CAPABILITY);
MountXDisplayStorage = ReadDB2<MountXDisplayRecord>("MountXDisplay.db2", HotfixStatements.SEL_MOUNT_X_DISPLAY); MountXDisplayStorage = ReadDB2<MountXDisplayRecord>("MountXDisplay.db2", HotfixStatements.SEL_MOUNT_X_DISPLAY);
MovieStorage = ReadDB2<MovieRecord>("Movie.db2", HotfixStatements.SEL_MOVIE); MovieStorage = ReadDB2<MovieRecord>("Movie.db2", HotfixStatements.SEL_MOVIE);
@@ -693,6 +694,7 @@ namespace Game.DataStorage
public static DB6Storage<ModifierTreeRecord> ModifierTreeStorage; public static DB6Storage<ModifierTreeRecord> ModifierTreeStorage;
public static DB6Storage<MountCapabilityRecord> MountCapabilityStorage; public static DB6Storage<MountCapabilityRecord> MountCapabilityStorage;
public static DB6Storage<MountRecord> MountStorage; public static DB6Storage<MountRecord> MountStorage;
public static DB6Storage<MountEquipmentRecord> MountEquipmentStorage;
public static DB6Storage<MountTypeXCapabilityRecord> MountTypeXCapabilityStorage; public static DB6Storage<MountTypeXCapabilityRecord> MountTypeXCapabilityStorage;
public static DB6Storage<MountXDisplayRecord> MountXDisplayStorage; public static DB6Storage<MountXDisplayRecord> MountXDisplayStorage;
public static DB6Storage<MovieRecord> MovieStorage; public static DB6Storage<MovieRecord> MovieStorage;
+9 -1
View File
@@ -197,7 +197,6 @@ namespace Game.DataStorage
public int MountSpecialSpellVisualKitID; public int MountSpecialSpellVisualKitID;
public bool HasFlag(MountFlags mountFlags) { return (Flags & (int)mountFlags) != 0; } public bool HasFlag(MountFlags mountFlags) { return (Flags & (int)mountFlags) != 0; }
public bool IsSelfMount() { return HasFlag(MountFlags.SelfMount); }
} }
public sealed class MountCapabilityRecord public sealed class MountCapabilityRecord
@@ -216,6 +215,15 @@ namespace Game.DataStorage
public bool HasFlag(MountCapabilityFlags mountCapabilityFlags) { return (Flags & (int)mountCapabilityFlags) != 0; } public bool HasFlag(MountCapabilityFlags mountCapabilityFlags) { return (Flags & (int)mountCapabilityFlags) != 0; }
} }
public sealed class MountEquipmentRecord
{
public uint Id;
public int Item;
public int BuffSpell;
public int Unknown820;
public uint LearnedBySpell;
}
public sealed class MountTypeXCapabilityRecord public sealed class MountTypeXCapabilityRecord
{ {
public uint Id; public uint Id;
@@ -1243,6 +1243,29 @@ namespace Game.Networking.Packets
public uint Result; public uint Result;
} }
class ApplyMountEquipmentResult : ServerPacket
{
public ObjectGuid ItemGUID;
public uint ItemID;
public ApplyResult Result = ApplyResult.Success;
public enum ApplyResult
{
Success = 0,
Failure = 1
}
public ApplyMountEquipmentResult() : base(ServerOpcodes.ApplyMountEquipmentResult, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(ItemGUID);
_worldPacket.WriteUInt32(ItemID);
_worldPacket.WriteBits(Result, 1);
_worldPacket.FlushBits();
}
}
class MissileCancel : ServerPacket class MissileCancel : ServerPacket
{ {
public MissileCancel() : base(ServerOpcodes.MissileCancel) { } public MissileCancel() : base(ServerOpcodes.MissileCancel) { }
+16 -1
View File
@@ -2169,7 +2169,7 @@ namespace Game.Spells
var mountDisplays = Global.DB2Mgr.GetMountDisplays(mountEntry.Id); var mountDisplays = Global.DB2Mgr.GetMountDisplays(mountEntry.Id);
if (mountDisplays != null) if (mountDisplays != null)
{ {
if (mountEntry.IsSelfMount()) if (mountEntry.HasFlag(MountFlags.IsSelfMount))
{ {
displayId = SharedConst.DisplayIdHiddenMount; displayId = SharedConst.DisplayIdHiddenMount;
} }
@@ -2191,6 +2191,17 @@ namespace Game.Spells
// TODO: CREATE TABLE mount_vehicle (mountId, vehicleCreatureId) for future mounts that are vehicles (new mounts no longer have proper data in MiscValue) // TODO: CREATE TABLE mount_vehicle (mountId, vehicleCreatureId) for future mounts that are vehicles (new mounts no longer have proper data in MiscValue)
//if (MountVehicle const* mountVehicle = sObjectMgr->GetMountVehicle(mountEntry->Id)) //if (MountVehicle const* mountVehicle = sObjectMgr->GetMountVehicle(mountEntry->Id))
// creatureEntry = mountVehicle->VehicleCreatureId; // creatureEntry = mountVehicle->VehicleCreatureId;
if (mode.HasFlag(AuraEffectHandleModes.Real) && !mountEntry.HasFlag(MountFlags.MountEquipmentEffectsSuppressed))
{
Player playerTarget = target.ToPlayer();
if (playerTarget != null)
{
var mountEquipment = CliDB.MountEquipmentStorage.Values.FirstOrDefault(record => playerTarget.HasSpell(record.LearnedBySpell));
if (mountEquipment != null)
playerTarget.CastSpell(playerTarget, (uint)mountEquipment.BuffSpell, this);
}
}
} }
CreatureTemplate creatureInfo = Global.ObjectMgr.GetCreatureTemplate(creatureEntry); CreatureTemplate creatureInfo = Global.ObjectMgr.GetCreatureTemplate(creatureEntry);
@@ -2234,7 +2245,11 @@ namespace Game.Spells
// need to remove ALL arura related to mounts, this will stop client crash with broom stick // need to remove ALL arura related to mounts, this will stop client crash with broom stick
// and never endless flying after using Headless Horseman's Mount // and never endless flying after using Headless Horseman's Mount
if (mode.HasAnyFlag(AuraEffectHandleModes.Real)) if (mode.HasAnyFlag(AuraEffectHandleModes.Real))
{
target.RemoveAurasByType(AuraType.Mounted); target.RemoveAurasByType(AuraType.Mounted);
foreach (var (_, mountEquipmentStore) in CliDB.MountEquipmentStorage)
target.RemoveOwnedAura((uint)mountEquipmentStore.BuffSpell);
}
if (mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountMask)) if (mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountMask))
{ {
+37
View File
@@ -5681,6 +5681,43 @@ namespace Game.Spells
Conversation.CreateConversation((uint)effectInfo.MiscValue, unitTarget, destTarget.GetPosition(), unitTarget.GetGUID(), GetSpellInfo()); Conversation.CreateConversation((uint)effectInfo.MiscValue, unitTarget, destTarget.GetPosition(), unitTarget.GetGUID(), GetSpellInfo());
} }
[SpellEffectHandler(SpellEffectName.ApplyMountEquipment)]
void EffectApplyMountEquipment()
{
if (effectHandleMode != SpellEffectHandleMode.LaunchTarget)
return;
Player playerTarget = unitTarget.ToPlayer();
if (playerTarget == null)
return;
foreach (var (_, mountEquipment) in CliDB.MountEquipmentStorage)
{
if (mountEquipment.LearnedBySpell == effectInfo.TriggerSpell)
{
playerTarget.LearnSpell(mountEquipment.LearnedBySpell, false, 0, true);
var mountAuras = playerTarget.GetAuraEffectsByType(AuraType.Mounted);
if (!mountAuras.Empty())
{
var mountEntry = Global.DB2Mgr.GetMount(mountAuras.FirstOrDefault().GetId());
if (mountEntry != null && !mountEntry.HasFlag(MountFlags.MountEquipmentEffectsSuppressed))
playerTarget.CastSpell(playerTarget, (uint)mountEquipment.BuffSpell, true);
}
}
else
{
playerTarget.RemoveOwnedAura((uint)mountEquipment.BuffSpell);
playerTarget.RemoveSpell(mountEquipment.LearnedBySpell, false, false, true);
}
}
ApplyMountEquipmentResult applyMountEquipmentResult = new();
applyMountEquipmentResult.ItemGUID = m_castItemGUID;
applyMountEquipmentResult.ItemID = m_castItemEntry;
applyMountEquipmentResult.Result = ApplyMountEquipmentResult.ApplyResult.Success;
playerTarget.SendPacket(applyMountEquipmentResult);
}
[SpellEffectHandler(SpellEffectName.SendChatMessage)] [SpellEffectHandler(SpellEffectName.SendChatMessage)]
void EffectSendChatMessage() void EffectSendChatMessage()
{ {
+48
View File
@@ -5166,4 +5166,52 @@ namespace Scripts.Spells.Generic
} }
} }
[Script] // 296837 - Comfortable Rider's Barding
class spell_gen_comfortable_riders_barding : AuraScript
{
static uint SPELL_DAZED = 1604;
bool _apply;
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SPELL_DAZED);
}
void HandleEffect(AuraEffect aurEff, AuraEffectHandleModes mode)
{
GetTarget().ApplySpellImmune(GetId(), SpellImmunity.Id, SPELL_DAZED, _apply);
}
public override void Register()
{
_apply = true;
OnEffectApply.Add(new EffectApplyHandler(HandleEffect, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
_apply = false;
OnEffectRemove.Add(new EffectApplyHandler(HandleEffect, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
}
}
[Script] // 297091 - Parachute
class spell_gen_saddlechute : AuraScript
{
static uint SPELL_PARACHUTE = 297092;
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SPELL_PARACHUTE);
}
void TriggerParachute(AuraEffect aurEff, AuraEffectHandleModes mode)
{
Unit target = GetTarget();
if (target.IsFlying() || target.IsFalling())
target.CastSpell(target, SPELL_PARACHUTE, new CastSpellExtraArgs(TriggerCastFlags.DontReportCastError));
}
public override void Register()
{
AfterEffectRemove.Add(new EffectApplyHandler(TriggerParachute, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
}
}
} }