diff --git a/Source/Game/Globals/ObjectManager.cs b/Source/Game/Globals/ObjectManager.cs index d9bfd8ac8..514428330 100644 --- a/Source/Game/Globals/ObjectManager.cs +++ b/Source/Game/Globals/ObjectManager.cs @@ -26,6 +26,7 @@ using Game.Entities; using Game.Mails; using Game.Maps; using Game.Misc; +using Game.Movement; using Game.Scripting; using Game.Spells; using System; @@ -9846,6 +9847,77 @@ namespace Game foreach (var poiPair in _questPOIStorage) poiPair.Value.InitializeQueryData(); } + public void LoadJumpChargeParams() + { + uint oldMSTime = Time.GetMSTime(); + + // need for reload case + _jumpChargeParams.Clear(); + + // 0 1 2 3 4 5 6 + SQLResult result = DB.World.Query("SELECT id, speed, treatSpeedAsMoveTimeSeconds, jumpGravity, spellVisualId, progressCurveId, parabolicCurveId FROM jump_charge_params"); + if (result.IsEmpty()) + return; + + do + { + int id = result.Read(0); + float speed = result.Read(1); + bool treatSpeedAsMoveTimeSeconds = result.Read(2); + float jumpGravity = result.Read(3); + Optional spellVisualId = new(); + Optional progressCurveId = new(); + Optional parabolicCurveId = new(); + + if (speed <= 0.0f) + { + Log.outError(LogFilter.Sql, $"Table `jump_charge_params` uses invalid speed {speed} for id {id}, set to default charge speed {MotionMaster.SPEED_CHARGE}."); + speed = MotionMaster.SPEED_CHARGE; + } + + if (jumpGravity <= 0.0f) + { + Log.outError(LogFilter.Sql, $"Table `jump_charge_params` uses invalid jump gravity {jumpGravity} for id {id}, set to default {MotionMaster.gravity}."); + jumpGravity = (float)MotionMaster.gravity; + } + + if (!result.IsNull(4)) + { + if (CliDB.SpellVisualStorage.ContainsKey(result.Read(4))) + spellVisualId.Set(result.Read(4)); + else + Log.outError(LogFilter.Sql, $"Table `jump_charge_params` references non-existing SpellVisual: {result.Read(4)} for id {id}, ignored."); + } + + if (!result.IsNull(5)) + { + if (CliDB.CurveStorage.ContainsKey(result.Read(5))) + progressCurveId.Set(result.Read(5)); + else + Log.outError(LogFilter.Sql, $"Table `jump_charge_params` references non-existing progress Curve: {result.Read(5)} for id {id}, ignored."); + } + + if (!result.IsNull(6)) + { + if (CliDB.CurveStorage.ContainsKey(result.Read(6))) + parabolicCurveId.Set(result.Read(6)); + else + Log.outError(LogFilter.Sql, $"Table `jump_charge_params` references non-existing parabolic Curve: {result.Read(6)} for id {id}, ignored."); + } + + JumpChargeParams jumpParams = new(); + jumpParams.Speed = speed; + jumpParams.TreatSpeedAsMoveTimeSeconds = treatSpeedAsMoveTimeSeconds; + jumpParams.JumpGravity = jumpGravity; + jumpParams.SpellVisualId = spellVisualId; + jumpParams.ProgressCurveId = progressCurveId; + jumpParams.ParabolicCurveId = parabolicCurveId; + _jumpChargeParams[id] = jumpParams; + + } while (result.NextRow()); + + Log.outInfo(LogFilter.ServerLoading, $"Loaded {_jumpChargeParams.Count} Player Choice locale strings in {Time.GetMSTimeDiffToNow(oldMSTime)} ms"); + } public MailLevelReward GetMailLevelReward(uint level, ulong raceMask) { @@ -10235,6 +10307,11 @@ namespace Game return _reservedNamesStorage.Contains(name.ToLower()); } + public JumpChargeParams GetJumpChargeParams(int id) + { + return _jumpChargeParams.LookupByKey(id); + } + //Vehicles public void LoadVehicleTemplate() { @@ -10392,6 +10469,7 @@ namespace Game Dictionary _pageTextStorage = new(); List _reservedNamesStorage = new(); Dictionary _sceneTemplateStorage = new(); + Dictionary _jumpChargeParams = new(); Dictionary _raceUnlockRequirementStorage = new(); List _classExpansionRequirementStorage = new(); diff --git a/Source/Game/Movement/MotionMaster.cs b/Source/Game/Movement/MotionMaster.cs index 6d488dcea..f86cb285a 100644 --- a/Source/Game/Movement/MotionMaster.cs +++ b/Source/Game/Movement/MotionMaster.cs @@ -23,6 +23,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Numerics; +using Framework.Dynamic; namespace Game.Movement { @@ -41,7 +42,7 @@ namespace Game.Movement return -1; } } - + public struct MovementGeneratorInformation { public MovementGeneratorType Type; @@ -80,7 +81,7 @@ namespace Game.Movement Unit _owner { get; } MovementGenerator _defaultGenerator { get; set; } SortedSet _generators { get; } = new(new MovementGeneratorComparator()); - + MultiMap _baseUnitStatesMap { get; } = new(); Queue _delayedActions { get; } = new(); MotionMasterFlags _flags { get; set; } @@ -736,7 +737,7 @@ namespace Game.Movement Add(movement); } - void MoveJumpWithGravity(Position pos, float speedXY, float gravity, uint id = EventId.Jump, bool hasOrientation = false, JumpArrivalCastArgs arrivalCast = null, SpellEffectExtraData spellEffectExtraData = null) + public void MoveJumpWithGravity(Position pos, float speedXY, float gravity, uint id = EventId.Jump, bool hasOrientation = false, JumpArrivalCastArgs arrivalCast = null, SpellEffectExtraData spellEffectExtraData = null) { Log.outDebug(LogFilter.Movement, $"MotionMaster.MoveJumpWithGravity: '{_owner.GetGUID()}', jumps to point Id: {id} ({pos})"); if (speedXY < 0.01f) @@ -767,7 +768,7 @@ namespace Game.Movement movement.BaseUnitState = UnitState.Jumping; Add(movement); } - + public void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, byte stepCount) { float step = 2 * MathFunctions.PI / stepCount * (clockwise ? -1.0f : 1.0f); @@ -1181,6 +1182,19 @@ namespace Game.Movement public ObjectGuid Target; } + public class JumpChargeParams + { + public float Speed; + + public bool TreatSpeedAsMoveTimeSeconds; + + public float JumpGravity; + + public Optional SpellVisualId; + public Optional ProgressCurveId; + public Optional ParabolicCurveId; + } + public struct ChaseRange { // this contains info that informs how we should path! diff --git a/Source/Game/Server/WorldManager.cs b/Source/Game/Server/WorldManager.cs index 2c93daade..91c0e9b3d 100644 --- a/Source/Game/Server/WorldManager.cs +++ b/Source/Game/Server/WorldManager.cs @@ -754,6 +754,9 @@ namespace Game Log.outInfo(LogFilter.ServerLoading, "Loading Player Choices Locales..."); Global.ObjectMgr.LoadPlayerChoicesLocale(); + Log.outInfo(LogFilter.ServerLoading, "Loading Jump Charge Params..."); + Global.ObjectMgr.LoadJumpChargeParams(); + CharacterDatabaseCleaner.CleanDatabase(); Log.outInfo(LogFilter.ServerLoading, "Loading the max pet number..."); diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index bd10216a2..1aaed1a82 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -5648,6 +5648,51 @@ namespace Game.Spells playerTarget.SendPacket(packet); } + + [SpellEffectHandler(SpellEffectName.JumpCharge)] + void EffectJumpCharge() + { + if (effectHandleMode != SpellEffectHandleMode.Launch) + return; + + if (unitCaster == null) + return; + + if (unitCaster.IsInFlight()) + return; + + JumpChargeParams jumpParams = Global.ObjectMgr.GetJumpChargeParams(effectInfo.MiscValue); + if (jumpParams == null) + return; + + float speed = jumpParams.Speed; + if (jumpParams.TreatSpeedAsMoveTimeSeconds) + speed = unitCaster.GetExactDist2d(destTarget) / jumpParams.Speed; + + Optional arrivalCast = new(); + if (effectInfo.TriggerSpell != 0) + { + arrivalCast.HasValue = true; + arrivalCast.Value.SpellId = effectInfo.TriggerSpell; + } + + Optional effectExtra = new(); + if (jumpParams.SpellVisualId.HasValue || jumpParams.ProgressCurveId.HasValue || jumpParams.ParabolicCurveId.HasValue) + { + effectExtra.HasValue = true; + if (jumpParams.SpellVisualId.HasValue) + effectExtra.Value.SpellVisualId = jumpParams.SpellVisualId.Value; + + if (jumpParams.ProgressCurveId.HasValue) + effectExtra.Value.ProgressCurveId = jumpParams.ProgressCurveId.Value; + + if (jumpParams.ParabolicCurveId.HasValue) + effectExtra.Value.ParabolicCurveId = jumpParams.ParabolicCurveId.Value; + } + + unitCaster.GetMotionMaster().MoveJumpWithGravity(destTarget, speed, jumpParams.JumpGravity, EventId.Jump, false, arrivalCast.Value, effectExtra.Value); + } + [SpellEffectHandler(SpellEffectName.LearnTransmogSet)] void EffectLearnTransmogSet() { diff --git a/sql/updates/world/master/2021_11_27_11_world.sql b/sql/updates/world/master/2021_11_27_11_world.sql new file mode 100644 index 000000000..0e2a2c818 --- /dev/null +++ b/sql/updates/world/master/2021_11_27_11_world.sql @@ -0,0 +1,15 @@ +DROP TABLE IF EXISTS `jump_charge_params`; +CREATE TABLE `jump_charge_params` ( + `id` int(11) NOT NULL, + `speed` float NOT NULL DEFAULT 42, + `treatSpeedAsMoveTimeSeconds` tinyint(1) NOT NULL DEFAULT 0, + `jumpGravity` float NOT NULL DEFAULT 19.29110527038574, + `spellVisualId` int(11) DEFAULT NULL, + `progressCurveId` int(11) DEFAULT NULL, + `parabolicCurveId` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `jump_charge_params` (`id`, `speed`, `treatSpeedAsMoveTimeSeconds`, `jumpGravity`, `progressCurveId`) VALUES +(2, 0.65, 1, 0.018818924203515052, 1636), -- Infernal Strike +(9, 0.88, 1, 0.010237299837172031, 1717); -- Metamorphosis