diff --git a/GameServer/Geometry/Coordinate.cs b/GameServer/Geometry/Coordinate.cs index 0751cc96..2c6961ae 100644 --- a/GameServer/Geometry/Coordinate.cs +++ b/GameServer/Geometry/Coordinate.cs @@ -65,4 +65,4 @@ public System.Numerics.Vector3 ToSysVector3() public readonly static Coordinate Nowhere = Create(-1, -1, -1); public readonly static Coordinate Zero = Create(0, 0, 0); -} \ No newline at end of file +} diff --git a/GameServer/Territory/Territory.cs b/GameServer/Territory/Territory.cs index 5b5e36db..3a4befcb 100644 --- a/GameServer/Territory/Territory.cs +++ b/GameServer/Territory/Territory.cs @@ -932,7 +932,7 @@ public void AddArea(AbstractArea area) IEnumerable mobs; if (area is Circle circle) { - mobs = region.GetNPCsInRadius(circle.Position, (ushort)circle.Radius, false, true).Cast().Where(n => !n.IsCannotTarget && n is not ShadowNPC); + mobs = region.GetNPCsInRadius(circle.Coordinate, (ushort)circle.Radius, false, true).Cast().Where(n => !n.IsCannotTarget && n is not ShadowNPC); } else { @@ -962,7 +962,7 @@ private void GatherMobsInTerritory() if (area is Circle circle) { - region.GetNPCsInRadius(circle.Position, (ushort)circle.Radius, false, true).Cast().Where(n => !n.IsCannotTarget && n is not ShadowNPC).Foreach(n => n.CurrentTerritory = this); + region.GetNPCsInRadius(circle.Coordinate, (ushort)circle.Radius, false, true).Cast().Where(n => !n.IsCannotTarget && n is not ShadowNPC).Foreach(n => n.CurrentTerritory = this); } else { diff --git a/GameServer/commands/gmcommands/checklos.cs b/GameServer/commands/gmcommands/checklos.cs index 67a9978b..c1f31a8d 100644 --- a/GameServer/commands/gmcommands/checklos.cs +++ b/GameServer/commands/gmcommands/checklos.cs @@ -35,7 +35,7 @@ public class CheckLosCommandHandler : AbstractCommandHandler, ICommandHandler { public async void OnCommand(GameClient client, string[] args) { - if (client.Player?.TargetObject == null && client.Player?.GroundTarget == null) + if (client.Player?.TargetObject == null && client.Player?.GroundTargetPosition == Position.Nowhere) { DisplayMessage(client, "You need a target to use this command."); return; @@ -45,7 +45,7 @@ public async void OnCommand(GameClient client, string[] args) if (client.Player.TargetObject != null) { var target = client.Player.TargetObject; - text.Add($"Target: {target.Name} (OID: {target.ObjectID}, distance: {Vector3.Distance(target.Position, client.Player.Position)})"); + text.Add($"Target: {target.Name} (OID: {target.ObjectID}, distance: {(int)target.Coordinate.DistanceTo(client.Player.Position)})"); text.Add($"Target in view (player's cache): {client.Player.TargetInView}"); var stats = new RaycastStats(); diff --git a/GameServer/commands/gmcommands/earthquake.cs b/GameServer/commands/gmcommands/earthquake.cs index 922b9b89..4b5e26bd 100644 --- a/GameServer/commands/gmcommands/earthquake.cs +++ b/GameServer/commands/gmcommands/earthquake.cs @@ -23,7 +23,7 @@ public void OnCommand(GameClient client, string[] args) intensity = 50.0f; duration = 1000.0f; int x, y, z = 0; - if (client.Player.GroundTarget == null) + if (client.Player.GroundTargetPosition == Position.Nowhere) { x = (int)client.Player.Position.X; y = (int)client.Player.Position.Y; @@ -97,7 +97,7 @@ public void OnCommand(GameClient client, string[] args) pakBis.WriteIntLowEndian((uint)y); pakBis.WriteIntLowEndian((uint)z); pakBis.Write(BitConverter.GetBytes(radius), 0, sizeof(System.Single)); - int distance = (int)System.Numerics.Vector3.Distance(player.Position, client.Player.Position); + int distance = (int)System.Numerics.(int)player.Coordinate.DistanceTo(client.Player.Position); float newIntensity = intensity * (1 - distance / radius); pakBis.Write(BitConverter.GetBytes(newIntensity), 0, sizeof(System.Single)); pakBis.Write(BitConverter.GetBytes(duration), 0, sizeof(System.Single)); diff --git a/GameServer/gameobjects/FeuDeCamp.cs b/GameServer/gameobjects/FeuDeCamp.cs index a0a62ebb..4af12e45 100644 --- a/GameServer/gameobjects/FeuDeCamp.cs +++ b/GameServer/gameobjects/FeuDeCamp.cs @@ -156,7 +156,7 @@ void ProximityCheck(object sender, ElapsedEventArgs e) { - foreach (GamePlayer Player in WorldMgr.GetPlayersCloseToSpot(this.CurrentRegionID, this.Position.X, this.Position.Y, this.Position.Z, Radius)) + foreach (GamePlayer Player in WorldMgr.GetPlayersCloseToSpot(this.Position.X, this.Position.Y, this.Position.Z, Radius)) { if (Player.IsSitting) { diff --git a/GameServer/gameobjects/GameNPC.cs b/GameServer/gameobjects/GameNPC.cs index dcf752d6..d49deaa1 100644 --- a/GameServer/gameobjects/GameNPC.cs +++ b/GameServer/gameobjects/GameNPC.cs @@ -1031,6 +1031,17 @@ public ushort SpawnHeading public short ZSpeedFactor => (short)((Motion.Destination.Z - Motion.Start.Z) / Motion.FullDistance); + + protected override Motion Motion + { + set + { + base.Motion = value; + BroadcastUpdate(); + } + } + + public Coordinate Destination => Motion.Destination; /// /// Stores the currentwaypoint that npc has to wander to @@ -1236,7 +1247,7 @@ public override GameObject TargetObject /// /// True if the mob is at its target position, else false. /// - public bool IsAtTargetPosition => Motion.Destination.Equals(Coordinate); + public bool IsAtTargetLocation => Motion.Destination.Equals(Coordinate); public override void TurnTo(Coordinate coordinate, bool sendUpdate = true) { diff --git a/GameServer/gameobjects/GamePlayer.cs b/GameServer/gameobjects/GamePlayer.cs index 815f7033..bdec086e 100644 --- a/GameServer/gameobjects/GamePlayer.cs +++ b/GameServer/gameobjects/GamePlayer.cs @@ -21,7 +21,6 @@ using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Numerics; using System.Reflection; using System.Text; @@ -1907,18 +1906,6 @@ public virtual void Release(eReleaseType releaseCommand, bool forced) TempProperties.removeProperty(DEATH_CONSTITUTION_LOSS_PROPERTY); - //Reset last valide position array to prevent /stuck avec /release - lock (m_lastUniqueLocations) - { - for (int i = 0; i < m_lastUniqueLocations.Length; i++) - { - GameLocation loc = m_lastUniqueLocations[i]; - loc.Position = Position; - loc.Heading = Heading; - loc.RegionID = CurrentRegionID; - } - } - if (m_releaseType == eReleaseType.Jail) { GameEventMgr.Notify(GamePlayerEvent.SendToJail, new SendToJailEventArgs() { GamePlayer = this, OriginalReputation = this.Reputation }); @@ -10822,7 +10809,7 @@ public override bool RemoveFromWorld() if (ObjectState == eObjectState.Active) { DismountSteed(true); - if (CurrentRegion.GetZone(Position) == null) + if (CurrentZone == null) { if (this is GamePlayer && this.Client.Account.PrivLevel < 3 && !(this as GamePlayer).TempProperties.getProperty("isbeingbanned", false)) { @@ -10907,11 +10894,11 @@ public override void Delete() /// Z target coordinate (0 to put player on floor) /// Target heading /// true if move succeeded, false if failed - public override bool MoveTo(ushort regionID, float x, float y, float z, ushort heading) + public override bool MoveTo(Position position) { //if we are jumping somewhere away from our house not using house.Exit //we need to make the server know we have left the house - if ((CurrentHouse != null || InHouse) && CurrentHouse.RegionID != regionID) + if ((CurrentHouse != null || InHouse) && CurrentHouse.RegionID != position.RegionID) { CurrentHouse = null; } @@ -10919,21 +10906,23 @@ public override bool MoveTo(ushort regionID, float x, float y, float z, ushort h if (IsOnHorse) IsOnHorse = false; //Get the destination region based on the ID - Region rgn = WorldMgr.GetRegion(regionID); + Region rgn = WorldMgr.GetRegion(position.RegionID); //If the region doesn't exist, return false or if they aren't allowed to zone here if (rgn == null || !GameServer.ServerRules.IsAllowedToZone(this, rgn)) return false; //If the x,y inside this region doesn't point to a zone //return false - if (rgn.GetZone(x, y) == null) + if (rgn.GetZone(position.Coordinate) == null) return false; Diving(waterBreath.Normal); if (SiegeWeapon != null) SiegeWeapon.ReleaseControl(); + + var positionBeforePort = Position; - if (regionID != CurrentRegionID) + if (position.RegionID != positionBeforePort.RegionID) { GameEventMgr.Notify(GamePlayerEvent.RegionChanging, this); if (!RemoveFromWorld()) @@ -10978,14 +10967,12 @@ public override bool MoveTo(ushort regionID, float x, float y, float z, ushort h //Current Speed = 0 when moved ... else X,Y,Z continue to be modified CurrentSpeed = 0; MovementStartTick = GameTimer.GetTickCount(); - Vector3 originalPoint = Position; - Position = new Vector3(x, y, z); - Heading = heading; + Position = position; //Remove the last update tick property, to prevent speedhack messages during zoning and teleporting! TempProperties.removeProperty(PlayerPositionUpdateHandler.LASTMOVEMENTTICK); //If the destination is in another region - if (regionID != CurrentRegionID) + if (position.RegionID != positionBeforePort.RegionID) { //Set our new region CurrentRegionID = regionID; @@ -11000,7 +10987,7 @@ public override bool MoveTo(ushort regionID, float x, float y, float z, ushort h Out.SendPlayerJump(false); // are we jumping far enough to force a complete refresh? - if (Vector3.Distance(Position, originalPoint) > WorldMgr.REFRESH_DISTANCE) + if (Coordinate.DistanceTo(positionBeforePort) > WorldMgr.REFRESH_DISTANCE) { RefreshWorld(); } @@ -11025,17 +11012,16 @@ public override bool MoveTo(ushort regionID, float x, float y, float z, ushort h if (hasPetToMove) { - Vector2 point = GameMath.GetPointFromHeading(Position, Heading, 64); - if (ControlledBody is GameNPC petBody) { - petBody.MoveInRegion(CurrentRegionID, point.X, point.Y, this.Position.Z + 10, (ushort)((this.Heading + 2048) % 4096), false); + var destination = Position.TurnedAround() + Vector.Create(Orientation, length: 64, z: 10); + petBody.MoveWithoutRemovingFromWorld(destination, false); if (petBody.ControlledNpcList != null) foreach (IControlledBrain icb in petBody.ControlledNpcList) if (icb != null && icb.Body is GameNPC petBody2 - && petBody2.IsWithinRadius(originalPoint, 500)) - petBody2.MoveInRegion(CurrentRegionID, point.X, point.Y, this.Position.Z + 10, (ushort)((this.Heading + 2048) % 4096), false); + && petBody2.Coordinate.DistanceTo(positionBeforePort) < 500) + petBody2.MoveWithoutRemovingFromWorld(destination, false); } } shadowNPC.MoveToPlayer(); @@ -11077,11 +11063,11 @@ public virtual void RefreshWorld() //Eden - Move to bind, and check if the loc is allowed public virtual bool MoveToBind() { - Region rgn = WorldMgr.GetRegion((ushort)BindRegion); - if (rgn == null || rgn.GetZone(BindXpos, BindYpos) == null) + Region rgn = WorldMgr.GetRegion(BindPosition.RegionID); + if (rgn == null || rgn.GetZone(BindPosition.Coordinate) == null) { if (log.IsErrorEnabled) - log.Error("Player: " + Name + " unknown bind point : (R/X/Y) " + BindRegion + "/" + BindXpos + "/" + BindYpos); + log.Error("Player: " + Name + " unknown bind point : (R/X/Y) " + BindPosition.RegionID + "/" + BindPosition.X + "/" + BindPosition.Y); //Kick the player, avoid server freeze Client.Out.SendPlayerQuit(true); SaveIntoDatabase(); @@ -11095,7 +11081,7 @@ public virtual bool MoveToBind() b.Account = Client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; - b.Reason = "X/Y/Zone : " + Position.X + "/" + Position.Y + "/" + CurrentRegion.ID; + b.Reason = "X/Y/RegionID : " + Position.X + "/" + Position.Y + "/" + Position.RegionID; GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); string message = "Unknown bind point, your account is banned, contact a GM."; @@ -11106,7 +11092,7 @@ public virtual bool MoveToBind() } if (GameServer.ServerRules.IsAllowedToMoveToBind(this)) - return MoveTo((ushort)BindRegion, BindXpos, BindYpos, BindZpos, (ushort)BindHeading); + return MoveTo(BindPosition); return false; } @@ -11316,17 +11302,10 @@ public long AreaUpdateTick public override Position Position { - get => IsMoving ? base.Position + MovementElapsedTicks * Velocity : base.Position; set { base.Position = value; - if (DBCharacter != null) - { - var p = base.Position; - DBCharacter.Xpos = (int)p.X; - DBCharacter.Ypos = (int)p.Y; - DBCharacter.Zpos = (int)p.Z; - } + if(DBCharacter != null) DBCharacter.SetPosition(value); } } @@ -11366,29 +11345,8 @@ public Zone LastPositionUpdateZone set { m_lastPositionUpdateZone = value; } } - - private uint m_lastPositionUpdateTick = 0; - - /// - /// The environment tick count when this players position was last updated - /// - public uint LastPositionUpdateTick - { - get { return m_lastPositionUpdateTick; } - set { m_lastPositionUpdateTick = value; } - } - - private Vector3 m_lastPositionUpdatePoint = new Vector3(0, 0, 0); - - /// - /// The last recorded position of this player - /// - public Vector3 LastPositionUpdatePoint - { - get { return m_lastPositionUpdatePoint; } - set { m_lastPositionUpdatePoint = value; } - } - + public Coordinate LastUpdateCoordinate => Motion.Start.Coordinate; + /// /// Gets or sets the players max Z for fall damage /// @@ -11407,15 +11365,12 @@ public override eRealm Realm } } - /// - /// Gets or sets the heading of this player - /// - public override ushort Heading + public override Angle Orientation { set { - base.Heading = value; - if (DBCharacter != null) DBCharacter.Direction = value; + base.Orientation = value; + if (DBCharacter != null) DBCharacter.Direction = value.InHeading; if (AttackState && ActiveWeaponSlot != eActiveWeaponSlot.Distance) { @@ -11901,33 +11856,17 @@ public virtual void Sit(bool sit) UpdatePlayerStatus(); } - /// - /// Sets the Living's ground-target Coordinates inside the current Region - /// - public override Vector3? GroundTarget + public override Position GroundTargetPosition { set { - base.GroundTarget = value; - if (value.HasValue) - Out.SendMessage(String.Format("You ground-target {0}", value), eChatType.CT_System, eChatLoc.CL_SystemWindow); - if (SiegeWeapon != null) - SiegeWeapon.GroundTarget = value; + base.GroundTargetPosition = value; + Out.SendMessage(String.Format("You ground-target {0},{1},{2}", value.X, value.Y, value.Z), eChatType.CT_System, eChatLoc.CL_SystemWindow); + if (SiegeWeapon != null) SiegeWeapon.GroundTargetPosition = value; } } - /// - /// Holds unique locations array - /// - protected readonly GameLocation[] m_lastUniqueLocations; - - /// - /// Gets unique locations array - /// - public GameLocation[] LastUniqueLocations - { - get { return m_lastUniqueLocations; } - } + public Position[] LastUniquePositions { get; } = new Position[4]; /// /// Updates Health, Mana, Sitting, Endurance, Concentration and Alive status to client @@ -12684,11 +12623,7 @@ public virtual WorldInventoryItem CreateItemOnTheGround(InventoryItem item) else { gameItem = new WorldInventoryItem(item); - - var itemloc = GameMath.GetPointFromHeading(this.Position, this.Heading, 30); - gameItem.Position = new Vector3(itemloc, 0); - gameItem.Heading = Heading; - gameItem.CurrentRegionID = CurrentRegionID; + gameItem.Position = Position + Vector.Create(Orientation, length: 30); gameItem.AddOwner(this); gameItem.AddToWorld(); @@ -12725,8 +12660,8 @@ public virtual bool PickupObject(GameObject floorObject, bool checkRange) { log.DebugFormat("Pickup error: {0} object x{1}, y{2}, z{3}, r{4} - player x{5}, y{6}, z{7}, r{8}", Name, - floorObject.Position.X, floorObject.Position.Y, floorObject.Position.Z, floorObject.CurrentRegionID, - Position.X, Position.Y, Position.Z, CurrentRegionID); + floorObject.Position.X, floorObject.Position.Y, floorObject.Position.Z, floorObject.Position.RegionID, + Position.X, Position.Y, Position.Z, Position.RegionID); } catch { @@ -13447,23 +13382,21 @@ public override void LoadFromDatabase(DataObject obj) #endregion #region setting world-init-position (delegate to PlayerCharacter dont make sense) - Position = new Vector3(DBCharacter.Xpos, DBCharacter.Ypos, DBCharacter.Zpos); - m_Heading = (ushort)DBCharacter.Direction; + Position = DBCharacter.GetPosition(); //important, use CurrentRegion property //instead because it sets the Region too CurrentRegionID = (ushort)DBCharacter.Region; - if (CurrentRegion == null || CurrentRegion.GetZone(Position) == null) + if (CurrentRegion == null || CurrentRegion.GetZone(Coordinate) == null) { - log.WarnFormat("Invalid region/zone on char load ({0}): x={1:N0} y={2:N0} z={3:N0} reg={4}; moving to bind point.", DBCharacter.Name, Position.X, Position.Y, Position.Z, DBCharacter.Region); - Position = new Vector3(DBCharacter.BindXpos, DBCharacter.BindYpos, DBCharacter.BindZpos); - m_Heading = (ushort)DBCharacter.BindHeading; - CurrentRegionID = (ushort)DBCharacter.BindRegion; + log.WarnFormat("Invalid region/zone on char load ({0}): x={1} y={2} z={3} reg={4}; moving to bind point." + , DBCharacter.Name, Coordinate.X, Coordinate.Y, Coordinate.Z, DBCharacter.Region); + Position = DBCharacter.GetBindPosition(); } - for (int i = 0; i < m_lastUniqueLocations.Length; i++) + for (int i = 0; i < LastUniquePositions.Length; i++) { - m_lastUniqueLocations[i] = new GameLocation(null, CurrentRegionID, Position.X, Position.Y, Position.Z); + LastUniquePositions[i] = Position; } #endregion @@ -13600,9 +13533,9 @@ public override void SaveIntoDatabase() DBCharacter.ActiveWeaponSlot = (byte)((byte)ActiveWeaponSlot | (byte)ActiveQuiverSlot); if (m_stuckFlag) { - lock (m_lastUniqueLocations) + lock (LastUniquePositions) { - GameLocation loc = m_lastUniqueLocations[m_lastUniqueLocations.Length - 1]; + DBCharacter.SetPosition(LastUniquePositions[LastUniquePositions.Length - 1]); DBCharacter.Xpos = (int)loc.Position.X; DBCharacter.Ypos = (int)loc.Position.Y; DBCharacter.Zpos = (int)loc.Position.Z; @@ -14031,17 +13964,17 @@ protected override void OnTick() fieldOfListen += (npc.Level - player.Level) * 3; } - double angle = GameMath.GetAngle(npc, player); + var angle = npc.GetAngleTo(player.Coordinate); //player in front fieldOfView /= 2.0; - bool canSeePlayer = (angle >= 360 - fieldOfView || angle < fieldOfView); + bool canSeePlayer = (angle.InDegrees >= 360 - fieldOfView || angle.InDegrees < fieldOfView); //If npc can not see nor hear the player, continue the loop fieldOfListen /= 2.0; if (canSeePlayer == false && - !(angle >= (45 + 60) - fieldOfListen && angle < (45 + 60) + fieldOfListen) && - !(angle >= (360 - 45 - 60) - fieldOfListen && angle < (360 - 45 - 60) + fieldOfListen)) + !(angle.InDegrees >= (45 + 60) - fieldOfListen && angle.InDegrees < (45 + 60) + fieldOfListen) && + !(angle.InDegrees >= (360 - 45 - 60) - fieldOfListen && angle.InDegrees < (360 - 45 - 60) + fieldOfListen)) continue; double chanceMod = 1.0; @@ -16942,7 +16875,6 @@ public GamePlayer(GameClient client, DOLCharacters dbChar) m_debuffBonus = new PropertyIndexer((int)eProperty.MaxProperty); m_buff4Bonus = new PropertyIndexer((int)eProperty.MaxProperty); m_itemBonus = new PropertyIndexer((int)eProperty.MaxProperty); - m_lastUniqueLocations = new GameLocation[4]; m_canFly = false; m_wanted = false; m_reputation = 0; diff --git a/GameServer/gameobjects/GameSiegeWeapon.cs b/GameServer/gameobjects/GameSiegeWeapon.cs index 0c9f28c2..610ef689 100644 --- a/GameServer/gameobjects/GameSiegeWeapon.cs +++ b/GameServer/gameobjects/GameSiegeWeapon.cs @@ -277,7 +277,7 @@ public void Move() { if (!CanUse()) return; if (!m_enableToMove) return; - if (Owner == null || Owner.GroundTarget == null) return; + if (Owner == null || Owner.GroundTargetPosition == Position.Nowhere) return; if (Owner == null || Owner.GroundTargetPosition == Position.Nowhere) return; if (Coordinate.DistanceTo(Owner.GroundTargetPosition) > 1000) { diff --git a/GameServer/gameutils/GuildBanner.cs b/GameServer/gameutils/GuildBanner.cs index 5470071a..3b156c48 100644 --- a/GameServer/gameutils/GuildBanner.cs +++ b/GameServer/gameutils/GuildBanner.cs @@ -10,7 +10,6 @@ using DOL.GS.Effects; using DOL.GS.ServerProperties; using System.Linq; -using System.Numerics; namespace DOL.GS { diff --git a/GameServer/keeps/IKeepManager.cs b/GameServer/keeps/IKeepManager.cs index e2ee293c..0882bd0d 100644 --- a/GameServer/keeps/IKeepManager.cs +++ b/GameServer/keeps/IKeepManager.cs @@ -60,8 +60,6 @@ public interface IKeepManager AbstractGameKeep GetKeepByID(int id); [Obsolete("This is going to be removed.")] IEnumerable GetKeepsCloseToSpot(ushort regionid, Vector3 point3d, int radius); [Obsolete("This is going to be removed.")] - ICollection GetKeepsCloseToSpot(ushort regionid, int x, int y, int z, int radius); - [Obsolete("Use .GetKeepCloseToSpot(Position, int) instead!")] AbstractGameKeep GetKeepCloseToSpot(ushort regionid, Vector3 point3d, int radius); [Obsolete("Use .GetKeepCloseToSpot(Position, int) instead!")] AbstractGameKeep GetKeepCloseToSpot(ushort regionid, int x, int y, int z, int radius); @@ -82,6 +80,8 @@ public interface IKeepManager bool IsEnemy(GameKeepDoor checker, GamePlayer target); bool IsEnemy(GameKeepComponent checker, GamePlayer target); byte GetHeightFromLevel(byte level); + Position GetBorderKeepPosition(int keepid); + [Obsolete("Use GetBorderKeepPosition(int) instead!")] void GetBorderKeepLocation(int keepid, out int x, out int y, out int z, out ushort heading); int GetRealmKeepBonusLevel(eRealm realm); int GetRealmTowerBonusLevel(eRealm realm); diff --git a/GameServer/keeps/KeepManager.cs b/GameServer/keeps/KeepManager.cs index 4a747f8e..38fa32e8 100644 --- a/GameServer/keeps/KeepManager.cs +++ b/GameServer/keeps/KeepManager.cs @@ -426,6 +426,7 @@ public virtual ICollection GetKeepsCloseToSpot(ushort regionid return closeKeeps; } + public virtual AbstractGameKeep GetKeepCloseToSpot(ushort regionid, int x, int y, int z, int radius) => GetKeepCloseToSpot(Position.Create(regionid,x,y), radius); diff --git a/GameServer/packets/Client/168/PlayerPositionUpdateHandler.cs b/GameServer/packets/Client/168/PlayerPositionUpdateHandler.cs index 7b0734b0..613370ed 100644 --- a/GameServer/packets/Client/168/PlayerPositionUpdateHandler.cs +++ b/GameServer/packets/Client/168/PlayerPositionUpdateHandler.cs @@ -133,17 +133,14 @@ public void HandlePacket(GameClient client, GSPacketIn packet) // move to bind if player fell through the floor if (realZ == 0) { - client.Player.MoveTo( - (ushort)client.Player.BindRegion, - client.Player.BindXpos, - client.Player.BindYpos, - (ushort)client.Player.BindZpos, - (ushort)client.Player.BindHeading - ); + client.Player.MoveTo(client.Player.BindPosition); return; } - var realPos = new Vector3(newZone.XOffset + xOffsetInZone, newZone.YOffset + yOffsetInZone, realZ); + var newCoordinate = Coordinate.Create( + x: newZone.Offset.X + xOffsetInZone, + y: newZone.Offset.Y + yOffsetInZone, + z: realZ); bool zoneChange = newZone != client.Player.LastPositionUpdateZone; if (zoneChange) @@ -180,17 +177,17 @@ public void HandlePacket(GameClient client, GSPacketIn packet) float coordsPerSec = 0; float jumpDetect = 0; - var timediff = GameTimer.GetTickCount() - client.Player.LastPositionUpdateTick; + int timediff = Environment.TickCount - client.Player.MovementStartTick; float distance = 0; if (timediff > 0) { - distance = Vector3.Distance(client.Player.LastPositionUpdatePoint, realPos); + distance = (int)client.Player.LastUpdateCoordinate.DistanceTo(newCoordinate); coordsPerSec = distance * 1000 / timediff; - if (distance < 100 && client.Player.LastPositionUpdatePoint.Z > 0) + if (distance < 100 && client.Player.LastUpdateCoordinate.Z > 0) { - jumpDetect = realZ - client.Player.LastPositionUpdatePoint.Z; + jumpDetect = realZ - client.Player.LastUpdateCoordinate.Z; } } @@ -207,9 +204,6 @@ public void HandlePacket(GameClient client, GSPacketIn packet) #endif #endregion DEBUG - client.Player.LastPositionUpdateTick = GameTimer.GetTickCount(); - client.Player.LastPositionUpdatePoint = realPos; - int tolerance = ServerProperties.Properties.CPS_TOLERANCE; if (client.Player.Steed != null && client.Player.Steed.MaxSpeed > 0) @@ -310,23 +304,16 @@ public void HandlePacket(GameClient client, GSPacketIn packet) client.Player.TempProperties.setProperty(LASTCPSTICK, environmentTick); } - var headingflag = packet.ReadShort(); - var flyingflag = packet.ReadShort(); - var flags = (byte)packet.ReadByte(); - - client.Player.Heading = (ushort)(headingflag & 0xFFF); - if (Vector3.DistanceSquared(client.Player.Position, realPos) > 0.1f) + if (client.Player.Coordinate.X != newCoordinate.X || client.Player.Coordinate.Y != newCoordinate.Y) + { client.Player.TempProperties.setProperty(LASTMOVEMENTTICK, client.Player.CurrentRegion.Time); - client.Player.Position = realPos; + } + client.Player.Position = Position.Create(client.Player.Position.RegionID, coordinate: newCoordinate, heading: (ushort)(headingflag & 0xFFF)); // update client zone information for waterlevel and diving if (zoneChange) client.Out.SendPlayerPositionAndObjectID(); - // used to predict current position, should be before - // any calculation (like fall damage) - client.Player.MovementStartTick = GameTimer.GetTickCount(); - // Begin ---------- New Area System ----------- if (client.Player.CurrentRegion.Time > client.Player.AreaUpdateTick) // check if update is needed { @@ -335,7 +322,7 @@ public void HandlePacket(GameClient client, GSPacketIn packet) // Because we may be in an instance we need to do the area check from the current region // rather than relying on the zone which is in the skinned region. - Tolakram - var newAreas = client.Player.CurrentRegion.GetAreasOfZone(newZone, client.Player.Position, true); + var newAreas = client.Player.CurrentRegion.GetAreasOfZone(newZone, client.Player.Coordinate, true); // Check for left areas if (oldAreas != null) @@ -516,18 +503,16 @@ public void HandlePacket(GameClient client, GSPacketIn packet) client.Player.TempProperties.setProperty(SHLASTFLY, SHlastFly); client.Player.TempProperties.setProperty(SHLASTSTATUS, SHlastStatus); client.Player.TempProperties.setProperty(SHSPEEDCOUNTER, SHcount); - lock (client.Player.LastUniqueLocations) + lock (client.Player.LastUniquePositions) { - GameLocation[] locations = client.Player.LastUniqueLocations; - GameLocation loc = locations[0]; - if (loc.Position != realPos || loc.RegionID != client.Player.CurrentRegionID) + var positions = client.Player.LastUniquePositions; + var pos = positions[0]; + var newPosition = client.Player.Position.With(coordinate: newCoordinate); + if (pos.Coordinate != newPosition.Coordinate) { - loc = locations[locations.Length - 1]; - Array.Copy(locations, 0, locations, 1, locations.Length - 1); - locations[0] = loc; - loc.Position = realPos; - loc.Heading = client.Player.Heading; - loc.RegionID = client.Player.CurrentRegionID; + pos = positions[positions.Length - 1]; + Array.Copy(positions, 0, positions, 1, positions.Length - 1); + positions[0] = newPosition; } } @@ -576,7 +561,7 @@ public void HandlePacket(GameClient client, GSPacketIn packet) //Riding is set here! if (client.Player.Steed != null && client.Player.Steed.ObjectState == GameObject.eObjectState.Active) - client.Player.Heading = client.Player.Steed.Heading; + client.Player.Orientation = client.Player.Steed.Orientation; if (zoneChange) // Update water level and diving flag for the new zone @@ -612,9 +597,10 @@ public void HandlePacket(GameClient client, GSPacketIn packet) } outpak.WriteShort(content); } - outpak.WriteShort((ushort)client.Player.Position.Z); - outpak.WriteShort((ushort)(client.Player.Position.X - client.Player.CurrentZone.XOffset)); - outpak.WriteShort((ushort)(client.Player.Position.Y - client.Player.CurrentZone.YOffset)); + var zoneCoord = client.Player.Coordinate - client.Player.CurrentZone.Offset; + outpak.WriteShort((ushort)zoneCoord.Z); + outpak.WriteShort((ushort)zoneCoord.X); + outpak.WriteShort((ushort)zoneCoord.Y); // Write Zone outpak.WriteShort(client.Player.CurrentZone.ZoneSkinID); @@ -627,7 +613,7 @@ public void HandlePacket(GameClient client, GSPacketIn packet) else { // Set Player always on ground, this is an "anti lag" packet - ushort contenthead = (ushort)(client.Player.Heading + (true ? 0x1000 : 0)); + ushort contenthead = (ushort)(client.Player.Orientation.InHeading + (true ? 0x1000 : 0)); outpak.WriteShort(contenthead); outpak.WriteShort(0); // No Fall Speed. } @@ -687,7 +673,7 @@ public void HandlePacket(GameClient client, GSPacketIn packet) outpak1124.WriteShort(currentZoneID); outpak1124.WriteShort(playerState); outpak1124.WriteShort((ushort)(client.Player.Steed?.RiderSlot(client.Player) ?? 0)); // fall damage flag coming in, steed seat position going out - outpak1124.WriteShort(client.Player.Heading); + outpak1124.WriteShort(client.Player.Orientation.InHeading); outpak1124.WriteByte(playerAction); outpak1124.WriteByte((byte)(client.Player.RPFlag ? 1 : 0)); outpak1124.WriteByte(0); @@ -856,26 +842,30 @@ private void _HandlePacket1124(GameClient client, GSPacketIn packet) client.Player.LastPositionUpdateZone = newZone; } - float coordsPerSec = 0; - float jumpDetect = 0; - uint timediff = GameTimer.GetTickCount() - client.Player.LastPositionUpdateTick; - float distance = 0; + var newPosition = Position.Create( + regionID: newZone.ZoneRegion.ID, + x: (int)newPlayerX, + y: (int)newPlayerY, + z: (int)newPlayerZ, + heading: (ushort)(newHeading & 0xFFF) + ); + + int coordsPerSec = 0; + int jumpDetect = 0; + int timediff = Environment.TickCount - client.Player.MovementStartTick; + int distance = 0; if (timediff > 0) { - distance = Vector3.Distance(client.Player.LastPositionUpdatePoint, new Vector3(newPlayerX, newPlayerY, newPlayerZ)); + distance = (int)client.Player.LastUpdateCoordinate.DistanceTo(newPosition.Coordinate); coordsPerSec = distance * 1000 / timediff; - if (distance < 100 && client.Player.LastPositionUpdatePoint.Z > 0) + if (distance < 100 && client.Player.LastUpdateCoordinate.Z > 0) { - jumpDetect = newPlayerZ - client.Player.LastPositionUpdatePoint.Z; + jumpDetect = (int)newPlayerZ - client.Player.LastUpdateCoordinate.Z; } } - client.Player.LastPositionUpdateTick = GameTimer.GetTickCount(); - client.Player.LastPositionUpdatePoint = new Vector3(newPlayerX, newPlayerY, newPlayerZ); - client.Player.Position = client.Player.LastPositionUpdatePoint; - int tolerance = ServerProperties.Properties.CPS_TOLERANCE; if (client.Player.Steed != null && client.Player.Steed.MaxSpeed > 0) @@ -981,18 +971,12 @@ private void _HandlePacket1124(GameClient client, GSPacketIn packet) } //client.Player.Heading = (ushort)(newHeading & 0xFFF); //patch 0024 expermental - if (Vector3.DistanceSquared(client.Player.Position, new Vector3(newPlayerX, newPlayerY, newPlayerZ)) > 0.1f) + if (client.Player.Position.X != newPosition.X || client.Player.Position.Y != newPosition.Y) { client.Player.TempProperties.setProperty(LASTMOVEMENTTICK, client.Player.CurrentRegion.Time); - client.Player.OnPlayerMove(); } - client.Player.Position = new Vector3(newPlayerX, newPlayerY, newPlayerZ); - client.Player.Heading = (ushort)(newHeading & 0xFFF); - - // used to predict current position, should be before - // any calculation (like fall damage) - client.Player.MovementStartTick = GameTimer.GetTickCount(); // experimental 0024 + client.Player.Position = newPosition; // Begin ---------- New Area System ----------- if (client.Player.CurrentRegion.Time > client.Player.AreaUpdateTick) // check if update is needed @@ -1002,7 +986,7 @@ private void _HandlePacket1124(GameClient client, GSPacketIn packet) // Because we may be in an instance we need to do the area check from the current region // rather than relying on the zone which is in the skinned region. - Tolakram - var newAreas = client.Player.CurrentRegion.GetAreasOfZone(newZone, client.Player.Position, true); + var newAreas = client.Player.CurrentRegion.GetAreasOfZone(newZone, client.Player.Coordinate); // Check for left areas if (oldAreas != null) @@ -1082,18 +1066,16 @@ private void _HandlePacket1124(GameClient client, GSPacketIn packet) return; } } - lock (client.Player.LastUniqueLocations) + + lock (client.Player.LastUniquePositions) { - GameLocation[] locations = client.Player.LastUniqueLocations; - GameLocation loc = locations[0]; - if (loc.Position.X != newPlayerX || loc.Position.Y != newPlayerY || loc.Position.Z != newPlayerZ || loc.RegionID != client.Player.CurrentRegionID) + var positions = client.Player.LastUniquePositions; + var pos = positions[0]; + if (pos.Coordinate != newPosition.Coordinate) { - loc = locations[locations.Length - 1]; - Array.Copy(locations, 0, locations, 1, locations.Length - 1); - locations[0] = loc; - loc.Position = new Vector3(newPlayerX, newPlayerY, newPlayerZ); - loc.Heading = client.Player.Heading; - loc.RegionID = client.Player.CurrentRegionID; + pos = positions[positions.Length - 1]; + Array.Copy(positions, 0, positions, 1, positions.Length - 1); + positions[0] = newPosition; } } @@ -1136,7 +1118,7 @@ private void _HandlePacket1124(GameClient client, GSPacketIn packet) if (client.Player.Steed != null && client.Player.Steed.ObjectState == GameObject.eObjectState.Active) { - client.Player.Heading = client.Player.Steed.Heading; + client.Player.Orientation = client.Player.Steed.Orientation; newHeading = (ushort)client.Player.Steed.ObjectID; } else if ((playerState >> 10) == 4) // patch 0062 fix bug on release preventing players from receiving res sickness @@ -1198,9 +1180,9 @@ private void _HandlePacket1124(GameClient client, GSPacketIn packet) outpak190.WriteShort((ushort)client.SessionID); outpak190.WriteShort((ushort)(client.Player.CurrentSpeed & 0x1FF)); outpak190.WriteShort((ushort)newPlayerZ); - var xoff = (ushort)(newPlayerX - (client.Player.CurrentZone?.XOffset ?? 0)); + var xoff = (ushort)(newPlayerX - (client.Player.CurrentZone?.Offset.X ?? 0)); outpak190.WriteShort(xoff); - var yoff = (ushort)(newPlayerY - (client.Player.CurrentZone?.YOffset ?? 0)); + var yoff = (ushort)(newPlayerY - (client.Player.CurrentZone?.Offset.Y ?? 0)); outpak190.WriteShort(yoff); outpak190.WriteShort(currentZoneID); outpak190.WriteShort(newHeading); diff --git a/GameServer/packets/Client/168/RegionChangeRequestHandler.cs b/GameServer/packets/Client/168/RegionChangeRequestHandler.cs index 5566dcfe..e853dd21 100644 --- a/GameServer/packets/Client/168/RegionChangeRequestHandler.cs +++ b/GameServer/packets/Client/168/RegionChangeRequestHandler.cs @@ -26,6 +26,7 @@ using DOL.GS.ServerRules; using log4net; +using DOL.GS.Geometry; namespace DOL.GS.PacketHandler.Client.v168 { @@ -73,8 +74,8 @@ public void HandlePacket(GameClient client, GSPacketIn packet) ChatUtil.SendDebugMessage(client, $"Invalid Jump (ZonePoint table): [{jumpSpotId}]{((zonePoint == null) ? ". Entry missing!" : ". TargetRegion is 0!")}"); zonePoint = new ZonePoint(); zonePoint.Id = jumpSpotId; - string zonePointLocation = $"Region {player.CurrentRegionID} and coordinates ({player.Position})"; - Log.Error($"ZonePoint {jumpSpotId} at {zonePointLocation} on client {client.Version} missing. Either ZonePoint missing or RegionChangeRequestHandler needs to be updated."); + string zonePointToText = $"Region {player.CurrentRegionID} and coordinates ({player.Coordinate})"; + Log.Error($"ZonePoint {jumpSpotId} at {zonePointToText} on client {client.Version} missing. Either ZonePoint missing or RegionChangeRequestHandler needs to be updated."); } if (client.Account.PrivLevel > 1) @@ -240,7 +241,7 @@ protected override void OnTick() } //move the player - player.MoveTo(m_zonePoint.TargetRegion, m_zonePoint.TargetX, m_zonePoint.TargetY, m_zonePoint.TargetZ, m_zonePoint.TargetHeading); + player.MoveTo(m_zonePoint.GetTargetPosition()); } } } diff --git a/GameServer/packets/Client/168/UseSkillHandler.cs b/GameServer/packets/Client/168/UseSkillHandler.cs index 853f87e8..4b7cde2e 100644 --- a/GameServer/packets/Client/168/UseSkillHandler.cs +++ b/GameServer/packets/Client/168/UseSkillHandler.cs @@ -16,6 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ +using DOL.GS.Geometry; using System; using System.Collections; using System.Collections.Generic; @@ -36,23 +37,21 @@ public class UseSkillHandler : IPacketHandler public void HandlePacket(GameClient client, GSPacketIn packet) { + var player = client.Player; if (client.Version >= GameClient.eClientVersion.Version1124) { - var x = packet.ReadFloatLowEndian(); - var y = packet.ReadFloatLowEndian(); - var z = packet.ReadFloatLowEndian(); - var speed = packet.ReadFloatLowEndian(); + var x = (int)packet.ReadFloatLowEndian(); + var y = (int)packet.ReadFloatLowEndian(); + var z = (int)packet.ReadFloatLowEndian(); + player.CurrentSpeed = (short)packet.ReadFloatLowEndian(); var heading = packet.ReadShort(); - - client.Player.Position = new Vector3(x, y, z); - client.Player.SetCurrentSpeed((short)speed); - client.Player.Heading = heading; + player.Position = Position.Create(player.Position.RegionID, x, y, z, heading); } int flagSpeedData = packet.ReadShort(); int index = packet.ReadByte(); int type = packet.ReadByte(); - new UseSkillAction(client.Player, flagSpeedData, index, type).Start(1); + new UseSkillAction(player, flagSpeedData, index, type).Start(1); } /// diff --git a/GameServer/packets/Client/168/UseSlotHandler.cs b/GameServer/packets/Client/168/UseSlotHandler.cs index b564af27..2350b47f 100644 --- a/GameServer/packets/Client/168/UseSlotHandler.cs +++ b/GameServer/packets/Client/168/UseSlotHandler.cs @@ -17,7 +17,7 @@ * */ -using System.Numerics; +using DOL.GS.Geometry; namespace DOL.GS.PacketHandler.Client.v168 { @@ -29,23 +29,21 @@ public class UseSlotHandler : IPacketHandler { public void HandlePacket(GameClient client, GSPacketIn packet) { + var player = client.Player; if (client.Version >= GameClient.eClientVersion.Version1124) { - var x = packet.ReadFloatLowEndian(); - var y = packet.ReadFloatLowEndian(); - var z = packet.ReadFloatLowEndian(); - var speed = packet.ReadFloatLowEndian(); + var x = (int)packet.ReadFloatLowEndian(); + var y = (int)packet.ReadFloatLowEndian(); + var z = (int)packet.ReadFloatLowEndian(); + player.CurrentSpeed = (short)packet.ReadFloatLowEndian(); var heading = packet.ReadShort(); - - client.Player.Position = new Vector3(x, y, z); - client.Player.SetCurrentSpeed((short)speed); - client.Player.Heading = heading; + player.Position = Position.Create(player.Position.RegionID, x, y, z, heading); } int flagSpeedData = packet.ReadShort(); int slot = packet.ReadByte(); int type = packet.ReadByte(); - new UseSlotAction(client.Player, flagSpeedData, slot, type).Start(1); + new UseSlotAction(player, flagSpeedData, slot, type).Start(1); } /// diff --git a/GameServer/packets/Client/168/UseSpellHandler.cs b/GameServer/packets/Client/168/UseSpellHandler.cs index 4473c737..7702b44f 100644 --- a/GameServer/packets/Client/168/UseSpellHandler.cs +++ b/GameServer/packets/Client/168/UseSpellHandler.cs @@ -16,10 +16,10 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ +using DOL.GS.Geometry; using System; using System.Collections; using System.Collections.Generic; -using System.Numerics; using System.Reflection; using log4net; @@ -43,15 +43,13 @@ public void HandlePacket(GameClient client, GSPacketIn packet) int spellLineIndex; if (client.Version >= GameClient.eClientVersion.Version1124) { - var x = packet.ReadFloatLowEndian(); - var y = packet.ReadFloatLowEndian(); - var z = packet.ReadFloatLowEndian(); - var speed = packet.ReadFloatLowEndian(); + var x = (int)packet.ReadFloatLowEndian(); + var y = (int)packet.ReadFloatLowEndian(); + var z = (int)packet.ReadFloatLowEndian(); + var speed = (short)packet.ReadFloatLowEndian(); var heading = packet.ReadShort(); - - client.Player.Position = new Vector3(x, y, z); - client.Player.SetCurrentSpeed((short)speed); - client.Player.Heading = heading; + client.Player.Position = Position.Create(client.Player.CurrentRegionID, x, y, z, heading); + client.Player.CurrentSpeed = speed; flagSpeedData = packet.ReadShort(); // target visible ? 0xA000 : 0x0000 spellLevel = packet.ReadByte(); spellLineIndex = packet.ReadByte(); @@ -76,15 +74,20 @@ public void HandlePacket(GameClient client, GSPacketIn packet) } else { - client.Player.Position = new Vector3(newZone.XOffset + xOffsetInZone, newZone.YOffset + yOffsetInZone, realZ); - client.Player.MovementStartTick = GameTimer.GetTickCount(); + client.Player.Position = Position.Create( + client.Player.CurrentRegionID, + newZone.Offset.X + xOffsetInZone, + newZone.Offset.Y + yOffsetInZone, + realZ, + client.Player.Orientation + ); } } spellLevel = packet.ReadByte(); spellLineIndex = packet.ReadByte(); - client.Player.Heading = (ushort)(heading & 0xfff); + client.Player.Orientation = Angle.Heading(heading); } new UseSpellAction(client.Player, flagSpeedData, spellLevel, spellLineIndex).Start(1); diff --git a/GameServer/packets/Client/168/warmapshowrequesthandler.cs b/GameServer/packets/Client/168/warmapshowrequesthandler.cs index 7d46644b..ecd3ea7e 100644 --- a/GameServer/packets/Client/168/warmapshowrequesthandler.cs +++ b/GameServer/packets/Client/168/warmapshowrequesthandler.cs @@ -16,6 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ +using DOL.GS.Geometry; using System; using System.Collections; @@ -128,54 +129,43 @@ public void HandlePacket(GameClient client, GSPacketIn packet) } } - int x = 0; - int y = 0; - int z = 0; - ushort heading = 0; + var portPosition = Position.Zero; switch (keepId) { - //sauvage - case 1: - //snowdonia - case 2: - //svas - case 3: - //vind - case 4: - //ligen - case 5: - //cain - case 6: + + case 1: //sauvage + case 2: //snowdonia + case 3: //svas + case 4: //vind + case 5: //ligen + case 6: //cain { - GameServer.KeepManager.GetBorderKeepLocation(keepId, out x, out y, out z, out heading); + portPosition = GameServer.KeepManager.GetBorderKeepPosition(keepId); break; } default: { if (keep != null && keep is GameKeep) { - FrontiersPortalStone stone = keep.TeleportStone; - if (stone != null) + var stone = keep.TeleportStone; + if (stone != null) { - heading = stone.Heading; - z = (int)stone.Position.Z; - stone.GetTeleportLocation(out x, out y); + var distance = Util.Random(50, 150); + var direction = stone.Orientation + Angle.Heading(Util.Random(- 500, 500)); + portPosition = stone.Position + Vector.Create(direction, distance); } else { - x = keep.X; - y = keep.Y; - z = keep.Z + 150; - heading = keep.Heading; + portPosition = Position.Create(regionID: 163, keep.X, keep.Y, keep.Z+150, keep.Orientation); } } break; } } - if (x != 0) + if (portPosition != Position.Zero) { - client.Player.MoveTo(163, x, y, z, heading); + client.Player.MoveTo(portPosition); } break; diff --git a/GameServer/packets/Server/IPacketLib.cs b/GameServer/packets/Server/IPacketLib.cs index d3c1743a..6cf58d18 100644 --- a/GameServer/packets/Server/IPacketLib.cs +++ b/GameServer/packets/Server/IPacketLib.cs @@ -22,6 +22,7 @@ using System.Numerics; using DOL.AI.Brain; using DOL.Database; +using DOL.GS.Geometry; using DOL.GS.Housing; using DOL.GS.Keeps; using DOL.GS.Quests; @@ -749,7 +750,9 @@ void SendDialogBox(eDialogCode code, ushort data1, ushort data2, ushort data3, u void SendConcentrationList(); void SendUpdateCraftingSkills(); void SendChangeTarget(GameObject newTarget); + [Obsolete("Use .SendChangeGroundTarget(Coordinate) instead!")] void SendChangeGroundTarget(Vector3 newTarget); + void SendChangeGroundTarget(Coordinate groundTarget); void SendPetWindow(GameLiving pet, ePetWindowAction windowAction, eAggressionState aggroState, eWalkState walkState); void SendPlaySound(eSoundType soundType, ushort soundID); void SendNPCsQuestEffect(GameNPC npc, eQuestIndicator indicator); @@ -761,6 +764,8 @@ void SendDialogBox(eDialogCode code, ushort data1, ushort data2, ushort data3, u void SendSiegeWeaponCloseInterface(); void SendSiegeWeaponInterface(GameSiegeWeapon siegeWeapon, int time); void SendLivingDataUpdate(GameLiving living, bool updateStrings); + void SendSoundEffect(ushort soundId, Position position, ushort radius); + [Obsolete("Use .SendSoundEffect(ushort,Position,ushort) instead!")] void SendSoundEffect(ushort soundId, ushort zoneId, ushort x, ushort y, ushort z, ushort radius); //keep void SendKeepInfo(IGameKeep keep); @@ -811,7 +816,9 @@ void SendDialogBox(eDialogCode code, ushort data1, ushort data2, ushort data3, u void SendVampireEffect(GameLiving living, bool show); void SendXFireInfo(byte flag); void SendMinotaurRelicMapRemove(byte id); + [Obsolete("Use .SendMinotaurRelicMapUpdate(byte, Position) instead!")] void SendMinotaurRelicMapUpdate(byte id, ushort region, int x, int y, int z); + void SendMinotaurRelicMapUpdate(byte id, Position position); void SendMinotaurRelicWindow(GamePlayer player, int spell, bool flag); void SendMinotaurRelicBarUpdate(GamePlayer player, int xp); diff --git a/GameServer/packets/Server/PacketLib1104.cs b/GameServer/packets/Server/PacketLib1104.cs index 3b14eca4..f69e8d65 100644 --- a/GameServer/packets/Server/PacketLib1104.cs +++ b/GameServer/packets/Server/PacketLib1104.cs @@ -22,7 +22,7 @@ using System.Reflection; using DOL.Database; - +using DOL.GS.Geometry; using log4net; @@ -145,7 +145,7 @@ public override void SendCharacterOverview(eRealm realm) Region region = WorldMgr.GetRegion((ushort)c.Region); if (region != null) { - locationDescription = m_gameClient.GetTranslatedSpotDescription(region, c.Xpos, c.Ypos, c.Zpos); + locationDescription = GamePlayerUtils.GetTranslatedSpotDescription(region, m_gameClient, c.GetPosition().Coordinate); } pak.FillString(locationDescription, 24); diff --git a/GameServer/packets/Server/PacketLib1110.cs b/GameServer/packets/Server/PacketLib1110.cs index 725003d6..b9f50c3c 100644 --- a/GameServer/packets/Server/PacketLib1110.cs +++ b/GameServer/packets/Server/PacketLib1110.cs @@ -28,6 +28,7 @@ using System.Numerics; using DOL.GS.Spells; using DOL.GS.Delve; +using DOL.GS.Geometry; namespace DOL.GS.PacketHandler { @@ -164,10 +165,10 @@ public override void SendSiegeWeaponAnimation(GameSiegeWeapon siegeWeapon) using (var pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.SiegeWeaponAnimation))) { pak.WriteInt((uint)siegeWeapon.ObjectID); - var pos = siegeWeapon.GroundTarget ?? siegeWeapon.TargetObject?.Position ?? Vector3.Zero; - pak.WriteInt((uint)pos.X); - pak.WriteInt((uint)pos.Y); - pak.WriteInt((uint)pos.Z); + var aimCoordinate = siegeWeapon.AimCoordinate; + pak.WriteInt((uint)aimCoordinate.X); + pak.WriteInt((uint)aimCoordinate.Y); + pak.WriteInt((uint)aimCoordinate.Z); pak.WriteInt((uint)(siegeWeapon.TargetObject == null ? 0 : siegeWeapon.TargetObject.ObjectID)); pak.WriteShort(siegeWeapon.Effect); pak.WriteShort((ushort)(siegeWeapon.SiegeWeaponTimer.TimeUntilElapsed)); // timer is no longer ( value / 100 ) @@ -188,12 +189,12 @@ public override void SendSiegeWeaponFireAnimation(GameSiegeWeapon siegeWeapon, i return; using (var pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.SiegeWeaponAnimation))) { - pak.WriteInt((uint)siegeWeapon.ObjectID); - var pos = siegeWeapon.GroundTarget ?? siegeWeapon.TargetObject?.Position ?? Vector3.Zero; - pos.Z += 50; - pak.WriteInt((uint)pos.X); - pak.WriteInt((uint)pos.Y); - pak.WriteInt((uint)pos.Z); + var targetPosition = siegeWeapon.TargetObject.Position; + if(targetPosition == Position.Nowhere) targetPosition = siegeWeapon.GroundTargetPosition; + pak.WriteInt((uint) siegeWeapon.ObjectID); + pak.WriteInt((uint) (targetPosition.X)); + pak.WriteInt((uint) (targetPosition.Y)); + pak.WriteInt((uint) (targetPosition.Z + 50)); pak.WriteInt((uint)(siegeWeapon.TargetObject == null ? 0 : siegeWeapon.TargetObject.ObjectID)); pak.WriteShort(siegeWeapon.Effect); pak.WriteShort((ushort)(timer)); // timer is no longer ( value / 100 ) diff --git a/GameServer/packets/Server/PacketLib1112.cs b/GameServer/packets/Server/PacketLib1112.cs index ebd52514..0461adee 100644 --- a/GameServer/packets/Server/PacketLib1112.cs +++ b/GameServer/packets/Server/PacketLib1112.cs @@ -566,7 +566,7 @@ public override void SendPlayerForgedPosition(GamePlayer player) // Write Speed if (player.Steed != null && player.Steed.ObjectState == GameObject.eObjectState.Active) { - player.Heading = player.Steed.Heading; + player.Orientation = player.Steed.Orientation; pak.WriteShort(0x1800); } else @@ -610,13 +610,10 @@ public override void SendPlayerForgedPosition(GamePlayer player) pak.WriteShort(content); } - // Get Off Corrd - var offX = player.Position.X - player.CurrentZone.XOffset; - var offY = player.Position.Y - player.CurrentZone.YOffset; - - pak.WriteShort((ushort)player.Position.Z); - pak.WriteShort((ushort)offX); - pak.WriteShort((ushort)offY); + var zoneCoordinate = player.Coordinate - player.CurrentZone.Offset; + pak.WriteShort((ushort)zoneCoordinate.Z); + pak.WriteShort((ushort)zoneCoordinate.X); + pak.WriteShort((ushort)zoneCoordinate.Y); // Write Zone pak.WriteShort(player.CurrentZone.ZoneSkinID); @@ -630,7 +627,7 @@ public override void SendPlayerForgedPosition(GamePlayer player) else { // Set Player always on ground, this is an "anti lag" packet - ushort contenthead = (ushort)(player.Heading + (true ? 0x1000 : 0)); + ushort contenthead = (ushort)(player.Orientation.InHeading + (true ? 0x1000 : 0)); pak.WriteShort(contenthead); // No Fall Speed. pak.WriteShort(0); diff --git a/GameServer/packets/Server/PacketLib1115.cs b/GameServer/packets/Server/PacketLib1115.cs index cc18c189..02dec9f3 100644 --- a/GameServer/packets/Server/PacketLib1115.cs +++ b/GameServer/packets/Server/PacketLib1115.cs @@ -135,11 +135,11 @@ public override void SendKeepInfo(IGameKeep keep) using (GSTCPPacketOut pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.KeepInfo))) { - pak.WriteShort((ushort)keep.KeepID); + pak.WriteShort(keep.KeepID); pak.WriteShort(0); pak.WriteInt((uint)keep.X); pak.WriteInt((uint)keep.Y); - pak.WriteShort((ushort)keep.Heading); + pak.WriteShort((ushort)keep.Orientation.InDegrees); pak.WriteByte((byte)keep.Realm); pak.WriteByte((byte)keep.Level);//level pak.WriteShort(0);//unk diff --git a/GameServer/packets/Server/PacketLib1124.cs b/GameServer/packets/Server/PacketLib1124.cs index fb83aa7f..d90404b9 100644 --- a/GameServer/packets/Server/PacketLib1124.cs +++ b/GameServer/packets/Server/PacketLib1124.cs @@ -65,16 +65,14 @@ public override void SendKeepInfo(IGameKeep keep) using (GSTCPPacketOut pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.KeepInfo))) { - pak.WriteShort((ushort)keep.KeepID); + pak.WriteShort(keep.KeepID); pak.WriteShort(0); pak.WriteInt((uint)keep.X); pak.WriteInt((uint)keep.Y); - pak.WriteShort((ushort)keep.Heading); + pak.WriteShort((ushort)keep.Orientation.InDegrees); pak.WriteByte((byte)keep.Realm); pak.WriteByte((byte)keep.Level);//level pak.WriteShort(0);//unk - pak.WriteByte(0);//model // patch 0072 - pak.WriteByte(0);//unk SendTCP(pak); } @@ -151,6 +149,8 @@ public override void SendLoginGranted(byte color) public override void SendNPCCreate(GameNPC npc) { + if (npc == null) + return; if (m_gameClient.Player == null || npc.IsVisibleTo(m_gameClient.Player) == false) return; @@ -187,20 +187,20 @@ public override void SendNPCCreate(GameNPC npc) else npcFlags = npc.Flags; - if (npc == null) - return; - if (!npc.IsAtTargetPosition) + if (!npc.IsAtTargetLocation) { speed = npc.CurrentSpeed; - speedZ = (ushort)npc.Velocity.Z; + speedZ = (ushort)npc.ZSpeedFactor; } pak.WriteShort((ushort)npc.ObjectID); pak.WriteShort((ushort)(speed)); - pak.WriteShort(npc.Heading); + pak.WriteShort(npc.Orientation.InHeading); pak.WriteShort((ushort)npc.Position.Z); pak.WriteInt((uint)npc.Position.X); pak.WriteInt((uint)npc.Position.Y); pak.WriteShort(speedZ); + pak.WriteShort(npc.Model); + pak.WriteByte(npc.Size); var model = npc.Model; var size = npc.Size; @@ -354,7 +354,7 @@ public override void SendPlayerCreate(GamePlayer playerToCreate) pak.WriteFloatLowEndian(playerToCreate.Position.Z); pak.WriteShort((ushort)playerToCreate.Client.SessionID); pak.WriteShort((ushort)playerToCreate.ObjectID); - pak.WriteShort(playerToCreate.Heading); + pak.WriteShort(playerToCreate.Orientation.InHeading); pak.WriteShort(playerToCreate.Model); pak.WriteByte(playerToCreate.GetDisplayLevel(m_gameClient.Player)); @@ -437,7 +437,7 @@ public override void SendPlayerPositionAndObjectID() pak.WriteFloatLowEndian(m_gameClient.Player.Position.Y); pak.WriteFloatLowEndian(m_gameClient.Player.Position.Z); pak.WriteShort((ushort)m_gameClient.Player.ObjectID); //This is the player's objectid not Sessionid!!! - pak.WriteShort(m_gameClient.Player.Heading); + pak.WriteShort(m_gameClient.Player.Orientation.InHeading); int flags = 0; Zone zone = m_gameClient.Player.CurrentZone; @@ -448,8 +448,8 @@ public override void SendPlayerPositionAndObjectID() if (zone.IsDungeon) { - pak.WriteShort((ushort)(zone.XOffset / 0x2000)); - pak.WriteShort((ushort)(zone.YOffset / 0x2000)); + pak.WriteShort((ushort)(zone.Offset.X / 0x2000)); + pak.WriteShort((ushort)(zone.Offset.Y / 0x2000)); } else { @@ -701,10 +701,10 @@ public override void SendSiegeWeaponAnimation(GameSiegeWeapon siegeWeapon) using (var pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.SiegeWeaponAnimation))) { pak.WriteInt((uint)siegeWeapon.ObjectID); - var pos = siegeWeapon.GroundTarget ?? siegeWeapon.TargetObject?.Position ?? Vector3.Zero; - pak.WriteInt((uint)pos.X); - pak.WriteInt((uint)pos.Y); - pak.WriteInt((uint)pos.Z); + var aimCoordinate = siegeWeapon.AimCoordinate; + pak.WriteInt((uint)aimCoordinate.X); + pak.WriteInt((uint)aimCoordinate.Y); + pak.WriteInt((uint)aimCoordinate.Z); pak.WriteInt((uint)(siegeWeapon.TargetObject == null ? 0 : siegeWeapon.TargetObject.ObjectID)); pak.WriteShort(siegeWeapon.Effect); pak.WriteShort((ushort)(siegeWeapon.SiegeWeaponTimer.TimeUntilElapsed)); @@ -891,13 +891,14 @@ protected override void WriteGroupMemberMapUpdate(GSTCPPacketOut pak, GameLiving if (living.CurrentSpeed != 0) { Zone zone = living.CurrentZone; + var zoneCoordinate = living.Coordinate - zone.Offset; if (zone == null) return; pak.WriteByte((byte)(0x40 | living.GroupIndex)); //Dinberg - ZoneSkinID for group members aswell. pak.WriteShort(zone.ZoneSkinID); - pak.WriteShort((ushort)(living.Position.X - zone.XOffset)); - pak.WriteShort((ushort)(living.Position.Y - zone.YOffset)); + pak.WriteShort((ushort)(zoneCoordinate.X)); + pak.WriteShort((ushort)(zoneCoordinate.Y)); } } diff --git a/GameServer/packets/Server/PacketLib1125.cs b/GameServer/packets/Server/PacketLib1125.cs index a2280455..2090eb9b 100644 --- a/GameServer/packets/Server/PacketLib1125.cs +++ b/GameServer/packets/Server/PacketLib1125.cs @@ -19,6 +19,7 @@ using DOL.Database; using DOL.GS.Effects; using DOL.GS.Finance; +using DOL.GS.Geometry; using DOL.GS.Housing; using DOL.GS.Profession; using DOL.GS.Spells; @@ -205,7 +206,7 @@ public override void SendCharacterOverview(eRealm realm) Region region = WorldMgr.GetRegion((ushort)c.Region); if (region != null) { - locationDescription = region.GetTranslatedSpotDescription(m_gameClient, c.Xpos, c.Ypos, c.Zpos); + locationDescription = region.GetTranslatedSpotDescription(m_gameClient, c.GetPosition().Coordinate); } if (locationDescription.Length > 23) // location name over 23 chars has to be truncated eg. "The Great Pyramid of Stygia" { diff --git a/GameServer/packets/Server/PacketLib1126.cs b/GameServer/packets/Server/PacketLib1126.cs index bc4dff06..11904090 100644 --- a/GameServer/packets/Server/PacketLib1126.cs +++ b/GameServer/packets/Server/PacketLib1126.cs @@ -17,6 +17,7 @@ * */ using DOL.Database; +using DOL.GS.Geometry; using log4net; using System; using System.Collections.Generic; @@ -182,7 +183,7 @@ public override void SendCharacterOverview(eRealm realm) string locationDescription = string.Empty; Region region = WorldMgr.GetRegion((ushort) c.Region); if (region != null) - locationDescription = m_gameClient.GetTranslatedSpotDescription(region, c.Xpos, c.Ypos, c.Zpos); + locationDescription = GamePlayerUtils.GetTranslatedSpotDescription(region, m_gameClient, c.GetPosition().Coordinate); string classname = ""; if (c.Class != 0) classname = ((eCharacterClass) c.Class).ToString(); diff --git a/GameServer/packets/Server/PacketLib168.cs b/GameServer/packets/Server/PacketLib168.cs index 1a975559..041afaee 100644 --- a/GameServer/packets/Server/PacketLib168.cs +++ b/GameServer/packets/Server/PacketLib168.cs @@ -36,12 +36,14 @@ using DOL.GS.Spells; using DOL.GS.Styles; using DOL.GS.Finance; +using DOL.GS.Geometry; using DOL.GS.Profession; using log4net; using DOL.GS.ServerProperties; using System.Numerics; using DOL.MobGroups; +using DOL.Geometry; namespace DOL.GS.PacketHandler { @@ -234,7 +236,8 @@ public virtual void SendCharacterOverview(eRealm realm) Region reg = WorldMgr.GetRegion((ushort)characters[j].Region); if (reg != null) { - var description = m_gameClient.GetTranslatedSpotDescription(reg, characters[j].Xpos, characters[j].Ypos, characters[j].Zpos); + var coordinate = characters[j].GetPosition().Coordinate; + var description = GamePlayerUtils.GetTranslatedSpotDescription(reg, m_gameClient, coordinate); pak.FillString(description, 24); } else @@ -534,11 +537,11 @@ public virtual void SendPlayerPositionAndObjectID() using (var pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.PositionAndObjectID))) { - pak.WriteShort((ushort)m_gameClient.Player.ObjectID); //This is the player's objectid not Sessionid!!! - pak.WriteShort((ushort)m_gameClient.Player.Position.Z); - pak.WriteInt((uint)m_gameClient.Player.Position.X); - pak.WriteInt((uint)m_gameClient.Player.Position.Y); - pak.WriteShort(m_gameClient.Player.Heading); + pak.WriteShort((ushort) m_gameClient.Player.ObjectID); //This is the player's objectid not Sessionid!!! + pak.WriteShort((ushort) m_gameClient.Player.Position.Z); + pak.WriteInt((uint) m_gameClient.Player.Position.X); + pak.WriteInt((uint) m_gameClient.Player.Position.Y); + pak.WriteShort(m_gameClient.Player.Orientation.InHeading); int flags = 0; if (m_gameClient.Player.CurrentZone.IsDivingEnabled) @@ -557,11 +560,11 @@ public virtual void SendPlayerJump(bool headingOnly) using (var pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.CharacterJump))) { - pak.WriteInt((uint)(headingOnly ? 0 : m_gameClient.Player.Position.X)); - pak.WriteInt((uint)(headingOnly ? 0 : m_gameClient.Player.Position.Y)); - pak.WriteShort((ushort)m_gameClient.Player.ObjectID); - pak.WriteShort((ushort)(headingOnly ? 0 : m_gameClient.Player.Position.Z)); - pak.WriteShort(m_gameClient.Player.Heading); + pak.WriteInt((uint) (headingOnly ? 0 : m_gameClient.Player.Position.X)); + pak.WriteInt((uint) (headingOnly ? 0 : m_gameClient.Player.Position.Y)); + pak.WriteShort((ushort) m_gameClient.Player.ObjectID); + pak.WriteShort((ushort) (headingOnly ? 0 : m_gameClient.Player.Position.Z)); + pak.WriteShort(m_gameClient.Player.Orientation.InHeading); if (m_gameClient.Player.InHouse == false || m_gameClient.Player.CurrentHouse == null) { pak.WriteShort(0); @@ -658,7 +661,12 @@ public virtual void SendMessage(string msg, eChatType type, eChatLoc loc) SendTCP(pak); } } + + protected ushort GetXOffsetInZone(GamePlayer player) + => (ushort)(player.Coordinate.X - player.CurrentZone.Offset.X); + protected ushort GetYOffsetInZone(GamePlayer player) + => (ushort)(player.Coordinate.Y - player.CurrentZone.Offset.Y); public virtual void SendPlayerCreate(GamePlayer playerToCreate) { if (playerToCreate == null) @@ -687,20 +695,20 @@ public virtual void SendPlayerCreate(GamePlayer playerToCreate) using (var pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.PlayerCreate))) { pak.WriteShort((ushort)playerToCreate.Client.SessionID); - pak.WriteShort((ushort)playerToCreate.ObjectID); + pak.WriteShort((ushort) playerToCreate.ObjectID); //pak.WriteInt(playerToCreate.X); //pak.WriteInt(playerToCreate.Y); - pak.WriteShort((ushort)playerRegion.GetXOffInZone(playerToCreate.Position.X, playerToCreate.Position.Y)); - pak.WriteShort((ushort)playerRegion.GetYOffInZone(playerToCreate.Position.X, playerToCreate.Position.Y)); + pak.WriteShort(GetXOffsetInZone(playerToCreate)); + pak.WriteShort(GetYOffsetInZone(playerToCreate)); //Dinberg:Instances - changing to ZoneSkinID for instance zones. - pak.WriteByte((byte)playerZone.ZoneSkinID); + pak.WriteByte((byte) playerZone.ZoneSkinID); pak.WriteByte(0); - pak.WriteShort((ushort)playerToCreate.Position.Z); - pak.WriteShort(playerToCreate.Heading); + pak.WriteShort((ushort) playerToCreate.Position.Z); + pak.WriteShort(playerToCreate.Orientation.InHeading); pak.WriteShort(playerToCreate.Model); //DOLConsole.WriteLine("send created player "+target.Player.Name+" to "+client.Player.Name+" alive="+target.Player.Alive); - pak.WriteByte((byte)(playerToCreate.IsAlive ? 0x1 : 0x0)); + pak.WriteByte((byte) (playerToCreate.IsAlive ? 0x1 : 0x0)); pak.WriteByte(0x00); pak.WriteByte(GameServer.ServerRules.GetLivingRealm(m_gameClient.Player, playerToCreate)); pak.WriteByte(playerToCreate.GetDisplayLevel(m_gameClient.Player)); @@ -760,11 +768,8 @@ public virtual void SendObjectUpdate(GameObject obj) return; } - var xOffsetInZone = (ushort)(obj.Position.X - z.XOffset); - var yOffsetInZone = (ushort)(obj.Position.Y - z.YOffset); - ushort xOffsetInTargetZone = 0; - ushort yOffsetInTargetZone = 0; - ushort zOffsetInTargetZone = 0; + var currentZoneCoord = obj.Coordinate - z.Offset; + var targetZoneCoord = Coordinate.Zero; int speed = 0; ushort targetZone = 0; @@ -809,17 +814,19 @@ public virtual void SendObjectUpdate(GameObject obj) flags |= 0x20; } - if (npc.IsMoving && !npc.IsAtTargetPosition) + if (npc.IsMoving && !npc.IsAtTargetLocation) { speed = npc.CurrentSpeed; - if (npc.TargetPosition != Vector3.Zero) + if (npc.Destination != Coordinate.Nowhere && npc.Destination != npc.Coordinate) { - Zone tz = npc.CurrentRegion.GetZone(npc.TargetPosition); + Zone tz = npc.CurrentRegion.GetZone(npc.Destination); if (tz != null) { - xOffsetInTargetZone = (ushort)(npc.TargetPosition.X - tz.XOffset); - yOffsetInTargetZone = (ushort)(npc.TargetPosition.Y - tz.YOffset); - zOffsetInTargetZone = (ushort)(npc.TargetPosition.Z); + targetZoneCoord = npc.Destination - tz.Offset; + + var overshootVector = targetZoneCoord - currentZoneCoord; + overshootVector = overshootVector * (100/overshootVector.Length); + targetZoneCoord += overshootVector; //Dinberg:Instances - zoneSkinID for object positioning clientside. targetZone = tz.ZoneSkinID; } @@ -844,20 +851,13 @@ public virtual void SendObjectUpdate(GameObject obj) { pak.WriteShort((ushort)speed); - if (obj is GameNPC) - { - pak.WriteShort((ushort)(obj.Heading & 0xFFF)); - } - else - { - pak.WriteShort(obj.Heading); - } - pak.WriteShort(xOffsetInZone); - pak.WriteShort(xOffsetInTargetZone); - pak.WriteShort(yOffsetInZone); - pak.WriteShort(yOffsetInTargetZone); - pak.WriteShort((ushort)obj.Position.Z); - pak.WriteShort(zOffsetInTargetZone); + pak.WriteShort(obj.Orientation.InHeading); + pak.WriteShort((ushort)currentZoneCoord.X); + pak.WriteShort((ushort)targetZoneCoord.X); + pak.WriteShort((ushort)currentZoneCoord.Y); + pak.WriteShort((ushort)targetZoneCoord.Y); + pak.WriteShort((ushort)currentZoneCoord.Z); + pak.WriteShort((ushort)targetZoneCoord.Z); pak.WriteShort((ushort)obj.ObjectID); pak.WriteShort((ushort)targetOID); //health @@ -936,12 +936,12 @@ public virtual void SendObjectCreate(GameObject obj) { pak.WriteShort((ushort)obj.ObjectID); if (obj is GameStaticItem) - pak.WriteShort((ushort)(obj as GameStaticItem).Emblem); + pak.WriteShort((ushort) (obj as GameStaticItem).Emblem); else pak.WriteShort(0); - pak.WriteShort(obj.Heading); - pak.WriteShort((ushort)obj.Position.Z); - pak.WriteInt((uint)obj.Position.X); - pak.WriteInt((uint)obj.Position.Y); + pak.WriteShort(obj.Orientation.InHeading); + pak.WriteShort((ushort) obj.Position.Z); + pak.WriteInt((uint) obj.Position.X); + pak.WriteInt((uint) obj.Position.Y); int flag = ((byte)obj.Realm & 3) << 4; ushort model = obj.Model; if (obj.IsUnderwater) @@ -1080,17 +1080,17 @@ public virtual void SendNPCCreate(GameNPC npc) { int speed = 0; ushort speedZ = 0; - if (npc.IsMoving && !npc.IsAtTargetPosition) + if (npc.IsMoving && !npc.IsAtTargetLocation) { speed = npc.CurrentSpeed; - speedZ = (ushort)npc.Velocity.Z; + speedZ = (ushort)npc.ZSpeedFactor; } - pak.WriteShort((ushort)npc.ObjectID); - pak.WriteShort((ushort)speed); - pak.WriteShort(npc.Heading); - pak.WriteShort((ushort)npc.Position.Z); - pak.WriteInt((uint)npc.Position.X); - pak.WriteInt((uint)npc.Position.Y); + pak.WriteShort((ushort) npc.ObjectID); + pak.WriteShort((ushort) speed); + pak.WriteShort(npc.Orientation.InHeading); + pak.WriteShort((ushort) npc.Position.Z); + pak.WriteInt((uint) npc.Position.X); + pak.WriteInt((uint) npc.Position.Y); pak.WriteShort(speedZ); var model = npc.Model; @@ -2111,7 +2111,7 @@ public virtual void SendPlayerForgedPosition(GamePlayer player) // Write Speed if (player.Steed != null && player.Steed.ObjectState == GameObject.eObjectState.Active) { - player.Heading = player.Steed.Heading; + player.Orientation = player.Steed.Orientation; pak.WriteShort(0x1800); } else @@ -2156,12 +2156,11 @@ public virtual void SendPlayerForgedPosition(GamePlayer player) } // Get Off Corrd - float offX = player.Position.X - player.CurrentZone.XOffset; - float offY = player.Position.Y - player.CurrentZone.YOffset; + var zoneCoord = player.Coordinate - player.CurrentZone.Offset; - pak.WriteShort((ushort)player.Position.Z); - pak.WriteShort((ushort)offX); - pak.WriteShort((ushort)offY); + pak.WriteShort((ushort)zoneCoord.Z); + pak.WriteShort((ushort)zoneCoord.X); + pak.WriteShort((ushort)zoneCoord.Y); // Write Zone pak.WriteByte((byte)player.CurrentZone.ZoneSkinID); @@ -2176,7 +2175,7 @@ public virtual void SendPlayerForgedPosition(GamePlayer player) else { // Set Player always on ground, this is an "anti lag" packet - ushort contenthead = (ushort)(player.Heading + (true ? 0x1000 : 0)); + ushort contenthead = (ushort)(player.Orientation.InHeading + (true ? 0x1000 : 0)); pak.WriteShort(contenthead); // No Fall Speed. pak.WriteShort(0); @@ -3135,13 +3134,18 @@ public void SendChangeTarget(GameObject newTarget) } } - public void SendChangeGroundTarget(Vector3 newTarget) + [Obsolete("Use .SendChangeGroundTarget(Coordinate) instead!")] + public void SendChangeGroundTarget(System.Numerics.Vector3 newTarget) + => SendChangeGroundTarget(Coordinate.Create((int)newTarget.X, (int)newTarget.Y, (int)newTarget.Z)); + + public void SendChangeGroundTarget(Coordinate newTarget) { using (var pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.ChangeGroundTarget))) { - pak.WriteInt((uint)newTarget.X); - pak.WriteInt((uint)newTarget.Y); - pak.WriteInt((uint)newTarget.Z); + var gtLoc = newTarget == Coordinate.Nowhere ? Coordinate.Zero : newTarget; + pak.WriteInt((uint)(gtLoc.X)); + pak.WriteInt((uint)(gtLoc.Y)); + pak.WriteInt((uint)(gtLoc.Z)); SendTCP(pak); } } @@ -3266,7 +3270,7 @@ public virtual void SendHouse(House house) pak.WriteShort((ushort)house.Position.Z); pak.WriteInt((uint)house.Position.X); pak.WriteInt((uint)house.Position.Y); - pak.WriteShort((ushort)house.Heading); + pak.WriteShort((ushort)house.Orientation); pak.WriteShort((ushort)house.PorchRoofColor); pak.WriteShort((ushort)house.GetPorchAndGuildEmblemFlags()); pak.WriteShort((ushort)house.Emblem); @@ -3298,10 +3302,10 @@ public virtual void SendRemoveHouse(House house) using (var pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.HouseCreate))) { - pak.WriteShort((ushort)house.HouseNumber); - pak.WriteShort((ushort)house.Position.Z); - pak.WriteInt((uint)house.Position.X); - pak.WriteInt((uint)house.Position.Y); + pak.WriteShort((ushort) house.HouseNumber); + pak.WriteShort((ushort) house.Position.Z); + pak.WriteInt((uint) house.Position.X); + pak.WriteInt((uint) house.Position.Y); pak.Fill(0x00, 15); pak.WriteByte(0x03); pak.WritePascalString(""); @@ -3390,9 +3394,9 @@ public virtual void SendEnterHouse(House house) { pak.WriteShort((ushort)house.HouseNumber); pak.WriteShort(25000); //constant! - pak.WriteInt((uint)house.Position.X); - pak.WriteInt((uint)house.Position.Y); - pak.WriteShort((ushort)house.Heading); //useless/ignored by client. + pak.WriteInt((uint) house.Position.X); + pak.WriteInt((uint) house.Position.Y); + pak.WriteShort((ushort) house.Orientation); //useless/ignored by client. pak.WriteByte(0x00); pak.WriteByte((byte)house.GetGuildEmblemFlags()); //emblem style pak.WriteShort((ushort)house.Emblem); //emblem @@ -3560,10 +3564,10 @@ public virtual void SendMovingObjectCreate(GameMovingObject obj) { pak.WriteShort((ushort)obj.ObjectID); pak.WriteShort(0); - pak.WriteShort(obj.Heading); - pak.WriteShort((ushort)obj.Position.Z); - pak.WriteInt((uint)obj.Position.X); - pak.WriteInt((uint)obj.Position.Y); + pak.WriteShort(obj.Orientation.InHeading); + pak.WriteShort((ushort) obj.Position.Z); + pak.WriteInt((uint) obj.Position.X); + pak.WriteInt((uint) obj.Position.Y); pak.WriteShort(obj.Model); int flag = (obj.Type() | ((byte)obj.Realm == 3 ? 0x40 : (byte)obj.Realm << 4) | obj.GetDisplayLevel(m_gameClient.Player) << 9); pak.WriteShort((ushort)flag); //(0x0002-for Ship,0x7D42-for catapult,0x9602,0x9612,0x9622-for ballista) @@ -3662,10 +3666,10 @@ public virtual void SendSiegeWeaponAnimation(GameSiegeWeapon siegeWeapon) using (var pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.SiegeWeaponAnimation))) { pak.WriteInt((uint)siegeWeapon.ObjectID); - var pos = siegeWeapon.GroundTarget ?? siegeWeapon.TargetObject?.Position ?? Vector3.Zero; - pak.WriteInt((uint)pos.X); - pak.WriteInt((uint)pos.Y); - pak.WriteInt((uint)pos.Z); + var aimCoordinate = siegeWeapon.AimCoordinate; + pak.WriteInt((uint)aimCoordinate.X); + pak.WriteInt((uint)aimCoordinate.Y); + pak.WriteInt((uint)aimCoordinate.Z); pak.WriteInt((uint)(siegeWeapon.TargetObject == null ? 0 : siegeWeapon.TargetObject.ObjectID)); pak.WriteShort(siegeWeapon.Effect); pak.WriteShort((ushort)(siegeWeapon.SiegeWeaponTimer.TimeUntilElapsed / 100)); @@ -3681,11 +3685,11 @@ public virtual void SendSiegeWeaponFireAnimation(GameSiegeWeapon siegeWeapon, in return; using (var pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.SiegeWeaponAnimation))) { - pak.WriteInt((uint)siegeWeapon.ObjectID); - pak.WriteInt((uint)(siegeWeapon.TargetObject == null ? 0 : siegeWeapon.TargetObject.Position.X)); - pak.WriteInt((uint)(siegeWeapon.TargetObject == null ? 0 : siegeWeapon.TargetObject.Position.Y)); - pak.WriteInt((uint)(siegeWeapon.TargetObject == null ? 0 : siegeWeapon.TargetObject.Position.Z + 50)); - pak.WriteInt((uint)(siegeWeapon.TargetObject == null ? 0 : siegeWeapon.TargetObject.ObjectID)); + pak.WriteInt((uint) siegeWeapon.ObjectID); + pak.WriteInt((uint) (siegeWeapon.TargetObject?.Position.X ?? 0)); + pak.WriteInt((uint) (siegeWeapon.TargetObject?.Position.Y ?? 0)); + pak.WriteInt((uint) (siegeWeapon.TargetObject?.Position.Z + 50 ?? 0)); + pak.WriteInt((uint) (siegeWeapon.TargetObject?.ObjectID ?? 0)); pak.WriteShort(siegeWeapon.Effect); pak.WriteShort((ushort)(timer / 100)); pak.WriteByte((byte)SiegeTimer.eAction.Fire); @@ -3722,6 +3726,18 @@ public virtual void SendLivingDataUpdate(GameLiving living, bool updateStrings) SendLivingEquipmentUpdate(living as GameNPC); } } + + public virtual void SendSoundEffect(ushort soundId, Position pos, ushort radius) + { + var region = WorldMgr.GetRegion(pos.RegionID); + if(region == null) return; + + var zone = region.GetZone(pos.Coordinate); + if(zone == null) return; + + var zoneCoord = pos - zone.Offset; + SendSoundEffect(soundId, zone.ID, (ushort)zoneCoord.X, (ushort)zoneCoord.Y, (ushort)zoneCoord.Z, radius); + } public virtual void SendSoundEffect(ushort soundId, ushort zoneId, ushort x, ushort y, ushort z, ushort radius) { @@ -3949,8 +3965,11 @@ public virtual void SendConsignmentMerchantMoney(long money) public virtual void SendMinotaurRelicMapRemove(byte id) { } + + public void SendMinotaurRelicMapUpdate(byte id, ushort region, int x, int y, int z) + => SendMinotaurRelicMapUpdate(id, Position.Create(region, x, y, z)); - public virtual void SendMinotaurRelicMapUpdate(byte id, ushort region, int x, int y, int z) + public virtual void SendMinotaurRelicMapUpdate(byte id, Position position) { } diff --git a/GameServer/packets/Server/PacketLib170.cs b/GameServer/packets/Server/PacketLib170.cs index 4d55577c..2620e37b 100644 --- a/GameServer/packets/Server/PacketLib170.cs +++ b/GameServer/packets/Server/PacketLib170.cs @@ -52,12 +52,11 @@ public override void SendKeepInfo(IGameKeep keep) { using (GSTCPPacketOut pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.KeepInfo))) { - - pak.WriteShort((ushort)keep.KeepID); + pak.WriteShort(keep.KeepID); pak.WriteShort(0);//zone id not sure pak.WriteInt((uint)keep.X); pak.WriteInt((uint)keep.Y); - pak.WriteShort((ushort)keep.Heading); + pak.WriteShort((ushort)keep.Orientation.InDegrees); pak.WriteByte((byte)keep.Realm); pak.WriteByte((byte)keep.Level);//level(not sure) pak.WriteShort(0);//unk diff --git a/GameServer/packets/Server/PacketLib171.cs b/GameServer/packets/Server/PacketLib171.cs index 78a01a1d..434c7dfc 100644 --- a/GameServer/packets/Server/PacketLib171.cs +++ b/GameServer/packets/Server/PacketLib171.cs @@ -58,7 +58,7 @@ public override void SendPlayerPositionAndObjectID() pak.WriteShort((ushort)m_gameClient.Player.Position.Z); pak.WriteInt((uint)m_gameClient.Player.Position.X); pak.WriteInt((uint)m_gameClient.Player.Position.Y); - pak.WriteShort(m_gameClient.Player.Heading); + pak.WriteShort(m_gameClient.Player.Orientation.InHeading); int flags = 0; if (m_gameClient.Player.CurrentZone.IsDivingEnabled) @@ -68,8 +68,8 @@ public override void SendPlayerPositionAndObjectID() pak.WriteByte(0x00); //TODO Unknown Zone zone = m_gameClient.Player.CurrentZone; if (zone == null) return; - pak.WriteShort((ushort)(zone.XOffset / 0x2000)); - pak.WriteShort((ushort)(zone.YOffset / 0x2000)); + pak.WriteShort((ushort)(zone.Offset.X / 0x2000)); + pak.WriteShort((ushort)(zone.Offset.Y / 0x2000)); //Dinberg - Changing to allow instances... pak.WriteShort(m_gameClient.Player.CurrentRegion.Skin); pak.WriteShort(0x00); //TODO: unknown, new in 1.71 @@ -91,7 +91,7 @@ public override void SendObjectCreate(GameObject obj) if (obj is GameStaticItem) pak.WriteShort((ushort)(obj as GameStaticItem).Emblem); else pak.WriteShort(0); - pak.WriteShort(obj.Heading); + pak.WriteShort(obj.Orientation.InHeading); pak.WriteShort((ushort)obj.Position.Z); pak.WriteInt((uint)obj.Position.X); pak.WriteInt((uint)obj.Position.Y); @@ -186,15 +186,15 @@ public override void SendNPCCreate(GameNPC npc) } else npcFlags = npc.Flags; - - if (!npc.IsAtTargetPosition) + + if (!npc.IsAtTargetLocation) { speed = npc.CurrentSpeed; - speedZ = (ushort)npc.Velocity.Z; + speedZ = (ushort)npc.ZSpeedFactor; } pak.WriteShort((ushort)npc.ObjectID); pak.WriteShort((ushort)(speed)); - pak.WriteShort(npc.Heading); + pak.WriteShort(npc.Orientation.InHeading); pak.WriteShort((ushort)npc.Position.Z); pak.WriteInt((uint)npc.Position.X); pak.WriteInt((uint)npc.Position.Y); diff --git a/GameServer/packets/Server/PacketLib172.cs b/GameServer/packets/Server/PacketLib172.cs index d6c731ef..6e14dd0d 100644 --- a/GameServer/packets/Server/PacketLib172.cs +++ b/GameServer/packets/Server/PacketLib172.cs @@ -72,9 +72,9 @@ public override void SendPlayerCreate(GamePlayer playerToCreate) pak.WriteShort((ushort)playerToCreate.Position.Z); //Dinberg:Instances - Zoneskin ID for clientside positioning 'bluff'. pak.WriteShort(playerZone.ZoneSkinID); - pak.WriteShort((ushort)playerRegion.GetXOffInZone(playerToCreate.Position.X, playerToCreate.Position.Y)); - pak.WriteShort((ushort)playerRegion.GetYOffInZone(playerToCreate.Position.X, playerToCreate.Position.Y)); - pak.WriteShort(playerToCreate.Heading); + pak.WriteShort(GetXOffsetInZone(playerToCreate)); + pak.WriteShort(GetYOffsetInZone(playerToCreate)); + pak.WriteShort(playerToCreate.Orientation.InHeading); pak.WriteByte(playerToCreate.GetFaceAttribute(eCharFacePart.EyeSize)); //1-4 = Eye Size / 5-8 = Nose Size pak.WriteByte(playerToCreate.GetFaceAttribute(eCharFacePart.LipSize)); //1-4 = Ear size / 5-8 = Kin size @@ -124,7 +124,7 @@ public override void SendPlayerForgedPosition(GamePlayer player) // Write Speed if (player.Steed != null && player.Steed.ObjectState == GameObject.eObjectState.Active) { - player.Heading = player.Steed.Heading; + player.Orientation = player.Steed.Orientation; pak.WriteShort(0x1800); } else @@ -169,12 +169,10 @@ public override void SendPlayerForgedPosition(GamePlayer player) } // Get Off Corrd - var offX = player.Position.X - player.CurrentZone.XOffset; - var offY = player.Position.Y - player.CurrentZone.YOffset; - - pak.WriteShort((ushort)player.Position.Z); - pak.WriteShort((ushort)offX); - pak.WriteShort((ushort)offY); + var zoneCoord = player.Coordinate - player.CurrentZone.Offset; + pak.WriteShort((ushort)zoneCoord.Z); + pak.WriteShort((ushort)zoneCoord.X); + pak.WriteShort((ushort)zoneCoord.Y); // Write Zone pak.WriteShort(player.CurrentZone.ZoneSkinID); @@ -188,7 +186,7 @@ public override void SendPlayerForgedPosition(GamePlayer player) else { // Set Player always on ground, this is an "anti lag" packet - ushort contenthead = (ushort)(player.Heading + (true ? 0x1000 : 0)); + ushort contenthead = (ushort)(player.Orientation.InHeading + (true ? 0x1000 : 0)); pak.WriteShort(contenthead); // No Fall Speed. pak.WriteShort(0); diff --git a/GameServer/packets/Server/PacketLib173.cs b/GameServer/packets/Server/PacketLib173.cs index ddc94d6c..75f2531a 100644 --- a/GameServer/packets/Server/PacketLib173.cs +++ b/GameServer/packets/Server/PacketLib173.cs @@ -26,6 +26,7 @@ using DOL.Language; using DOL.Database; using DOL.GS.Effects; +using DOL.GS.Geometry; using DOL.GS.Keeps; using DOL.GS.Quests; using DOL.GS.Spells; @@ -300,7 +301,8 @@ public override void SendCharacterOverview(eRealm realm) Region reg = WorldMgr.GetRegion((ushort)characters[j].Region); if (reg != null) { - var description = m_gameClient.GetTranslatedSpotDescription(reg, characters[j].Xpos, characters[j].Ypos, characters[j].Zpos); + var coordinate = characters[j].GetPosition().Coordinate; + var description = GamePlayerUtils.GetTranslatedSpotDescription(reg, m_gameClient, coordinate); pak.FillString(description, 24); } else @@ -446,14 +448,13 @@ public override void SendKeepInfo(IGameKeep keep) return; using (GSTCPPacketOut pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.KeepInfo))) { - - pak.WriteShort((ushort)keep.KeepID); + pak.WriteShort(keep.KeepID); pak.WriteShort(0); pak.WriteInt((uint)keep.X); pak.WriteInt((uint)keep.Y); - pak.WriteShort((ushort)keep.Heading); + pak.WriteShort((ushort)keep.Orientation.InDegrees); pak.WriteByte((byte)keep.Realm); - pak.WriteByte((byte)keep.Level);//level + pak.WriteByte(keep.Level);//level pak.WriteShort(0);//unk pak.WriteByte(0x52);//model pak.WriteByte(0);//unk diff --git a/GameServer/packets/Server/PacketLib174.cs b/GameServer/packets/Server/PacketLib174.cs index 16554253..ef0ba171 100644 --- a/GameServer/packets/Server/PacketLib174.cs +++ b/GameServer/packets/Server/PacketLib174.cs @@ -24,6 +24,7 @@ using DOL.Language; using DOL.Database; using DOL.GS.Effects; +using DOL.GS.Geometry; using DOL.GS.Keeps; using DOL.GS.PlayerTitles; using DOL.GS.Spells; @@ -117,7 +118,8 @@ public override void SendCharacterOverview(eRealm realm) Region reg = WorldMgr.GetRegion((ushort)characters[j].Region); if (reg != null) { - var description = m_gameClient.GetTranslatedSpotDescription(reg, characters[j].Xpos, characters[j].Ypos, characters[j].Zpos); + var coordinate = characters[j].GetPosition().Coordinate; + var description = GamePlayerUtils.GetTranslatedSpotDescription(reg, m_gameClient, coordinate); pak.FillString(description, 24); } else @@ -286,9 +288,9 @@ public override void SendPlayerCreate(GamePlayer playerToCreate) pak.WriteShort((ushort)playerToCreate.Position.Z); //Dinberg:Instances - zoneSkinID for object positioning clientside (as zones are hardcoded). pak.WriteShort(playerZone.ZoneSkinID); - pak.WriteShort((ushort)playerRegion.GetXOffInZone(playerToCreate.Position.X, playerToCreate.Position.Y)); - pak.WriteShort((ushort)playerRegion.GetYOffInZone(playerToCreate.Position.X, playerToCreate.Position.Y)); - pak.WriteShort(playerToCreate.Heading); + pak.WriteShort(GetXOffsetInZone(playerToCreate)); + pak.WriteShort(GetYOffsetInZone(playerToCreate)); + pak.WriteShort(playerToCreate.Orientation.InHeading); pak.WriteByte(playerToCreate.GetFaceAttribute(eCharFacePart.EyeSize)); //1-4 = Eye Size / 5-8 = Nose Size pak.WriteByte(playerToCreate.GetFaceAttribute(eCharFacePart.LipSize)); //1-4 = Ear size / 5-8 = Kin size @@ -332,7 +334,7 @@ public override void SendPlayerPositionAndObjectID() pak.WriteShort((ushort)m_gameClient.Player.Position.Z); pak.WriteInt((uint)m_gameClient.Player.Position.X); pak.WriteInt((uint)m_gameClient.Player.Position.Y); - pak.WriteShort(m_gameClient.Player.Heading); + pak.WriteShort(m_gameClient.Player.Orientation.InHeading); int flags = 0; Zone zone = m_gameClient.Player.CurrentZone; @@ -347,8 +349,8 @@ public override void SendPlayerPositionAndObjectID() if (zone.IsDungeon) { - pak.WriteShort((ushort)(zone.XOffset / 0x2000)); - pak.WriteShort((ushort)(zone.YOffset / 0x2000)); + pak.WriteShort((ushort)(zone.Offset.X / 0x2000)); + pak.WriteShort((ushort)(zone.Offset.Y / 0x2000)); } else { @@ -380,8 +382,9 @@ protected virtual void WriteGroupMemberMapUpdate(GSTCPPacketOut pak, GameLiving pak.WriteByte((byte)(0x40 | living.GroupIndex)); //Dinberg - ZoneSkinID for group members aswell. pak.WriteShort(zone.ZoneSkinID); - pak.WriteShort((ushort)(living.Position.X - zone.XOffset)); - pak.WriteShort((ushort)(living.Position.Y - zone.YOffset)); + var zoneCoord = living.Coordinate - zone.Offset; + pak.WriteShort((ushort)(zoneCoord.X)); + pak.WriteShort((ushort)(zoneCoord.Y)); } } diff --git a/GameServer/packets/Server/PacketLib175.cs b/GameServer/packets/Server/PacketLib175.cs index 9b12398e..481ed715 100644 --- a/GameServer/packets/Server/PacketLib175.cs +++ b/GameServer/packets/Server/PacketLib175.cs @@ -476,9 +476,9 @@ public override void SendPlayerCreate(GamePlayer playerToCreate) pak.WriteShort((ushort)playerToCreate.Position.Z); //Dinberg:Instances - as with all objects, we need to use a zoneSkinID for clientside positioning. pak.WriteShort(playerZone.ZoneSkinID); - pak.WriteShort((ushort)playerRegion.GetXOffInZone(playerToCreate.Position.X, playerToCreate.Position.Y)); - pak.WriteShort((ushort)playerRegion.GetYOffInZone(playerToCreate.Position.X, playerToCreate.Position.Y)); - pak.WriteShort(playerToCreate.Heading); + pak.WriteShort(GetXOffsetInZone(playerToCreate)); + pak.WriteShort(GetYOffsetInZone(playerToCreate)); + pak.WriteShort(playerToCreate.Orientation.InHeading); pak.WriteByte(playerToCreate.GetFaceAttribute(eCharFacePart.EyeSize)); //1-4 = Eye Size / 5-8 = Nose Size pak.WriteByte(playerToCreate.GetFaceAttribute(eCharFacePart.LipSize)); //1-4 = Ear size / 5-8 = Kin size diff --git a/GameServer/packets/Server/PacketLib176.cs b/GameServer/packets/Server/PacketLib176.cs index 281b1651..9c238735 100644 --- a/GameServer/packets/Server/PacketLib176.cs +++ b/GameServer/packets/Server/PacketLib176.cs @@ -109,7 +109,7 @@ public override void SendObjectCreate(GameObject obj) else pak.WriteShort(0); - pak.WriteShort(obj.Heading); + pak.WriteShort(obj.Orientation.InHeading); pak.WriteShort((ushort)obj.Position.Z); pak.WriteInt((uint)obj.Position.X); pak.WriteInt((uint)obj.Position.Y); @@ -373,7 +373,7 @@ public override void SendHouse(House house) pak.WriteShort((ushort)house.Position.Z); pak.WriteInt((uint)house.Position.X); pak.WriteInt((uint)house.Position.Y); - pak.WriteShort((ushort)house.Heading); + pak.WriteShort((ushort)house.Orientation); pak.WriteShort((ushort)house.PorchRoofColor); pak.WriteShort((ushort)(house.GetPorchAndGuildEmblemFlags() | (house.Emblem & 0x010000) >> 13));//new Guild Emblem pak.WriteShort((ushort)house.Emblem); @@ -403,7 +403,7 @@ public override void SendEnterHouse(House house) pak.WriteShort((ushort)25000); //constant! pak.WriteInt((uint)house.Position.X); pak.WriteInt((uint)house.Position.Y); - pak.WriteShort((ushort)house.Heading); //useless/ignored by client. + pak.WriteShort((ushort)house.Orientation); //useless/ignored by client. pak.WriteByte(0x00); pak.WriteByte((byte)(house.GetGuildEmblemFlags() | (house.Emblem & 0x010000) >> 14));//new Guild Emblem pak.WriteShort((ushort)house.Emblem); //emblem diff --git a/GameServer/packets/Server/PacketLib180.cs b/GameServer/packets/Server/PacketLib180.cs index 8dec3203..4311f6a9 100644 --- a/GameServer/packets/Server/PacketLib180.cs +++ b/GameServer/packets/Server/PacketLib180.cs @@ -160,9 +160,9 @@ public override void SendPlayerCreate(GamePlayer playerToCreate) pak.WriteShort((ushort)playerToCreate.Position.Z); //Dinberg:Instances - send out the 'fake' zone ID to the client for positioning purposes. pak.WriteShort(playerZone.ZoneSkinID); - pak.WriteShort((ushort)playerRegion.GetXOffInZone(playerToCreate.Position.X, playerToCreate.Position.Y)); - pak.WriteShort((ushort)playerRegion.GetYOffInZone(playerToCreate.Position.X, playerToCreate.Position.Y)); - pak.WriteShort(playerToCreate.Heading); + pak.WriteShort(GetXOffsetInZone(playerToCreate)); + pak.WriteShort(GetYOffsetInZone(playerToCreate)); + pak.WriteShort(playerToCreate.Orientation.InHeading); pak.WriteByte(playerToCreate.GetFaceAttribute(eCharFacePart.EyeSize)); //1-4 = Eye Size / 5-8 = Nose Size pak.WriteByte(playerToCreate.GetFaceAttribute(eCharFacePart.LipSize)); //1-4 = Ear size / 5-8 = Kin size diff --git a/GameServer/packets/Server/PacketLib186.cs b/GameServer/packets/Server/PacketLib186.cs index 94b50b49..1056654f 100644 --- a/GameServer/packets/Server/PacketLib186.cs +++ b/GameServer/packets/Server/PacketLib186.cs @@ -16,6 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ +using DOL.GS.Geometry; using System; using log4net; using DOL.GS.Quests; @@ -113,16 +114,16 @@ public override void SendMinotaurRelicMapRemove(byte id) } } - public override void SendMinotaurRelicMapUpdate(byte id, ushort region, int x, int y, int z) + public override void SendMinotaurRelicMapUpdate(byte id, Position position) { using (GSTCPPacketOut pak = new GSTCPPacketOut(GetPacketCode(eServerPackets.MinotaurRelicMapUpdate))) { pak.WriteIntLowEndian((uint)id); - pak.WriteIntLowEndian((uint)region); - pak.WriteIntLowEndian((uint)x); - pak.WriteIntLowEndian((uint)y); - pak.WriteIntLowEndian((uint)z); + pak.WriteIntLowEndian((uint)position.RegionID); + pak.WriteIntLowEndian((uint)position.X); + pak.WriteIntLowEndian((uint)position.Y); + pak.WriteIntLowEndian((uint)position.Z); SendTCP(pak); } diff --git a/GameServer/packets/Server/PacketLib189.cs b/GameServer/packets/Server/PacketLib189.cs index 39cbd5d6..cb189f4d 100644 --- a/GameServer/packets/Server/PacketLib189.cs +++ b/GameServer/packets/Server/PacketLib189.cs @@ -421,7 +421,7 @@ public override void SendHouse(House house) pak.WriteShort((ushort)house.Position.Z); pak.WriteInt((uint)house.Position.X); pak.WriteInt((uint)house.Position.Y); - pak.WriteShort((ushort)house.Heading); + pak.WriteShort((ushort)house.Orientation); pak.WriteShort((ushort)house.PorchRoofColor); int flagPorchAndGuildEmblem = (house.Emblem & 0x010000) >> 13;//new Guild Emblem if (house.Porch) @@ -521,7 +521,7 @@ public override void SendEnterHouse(House house) pak.WriteShort((ushort)25000); //constant! pak.WriteInt((uint)house.Position.X); pak.WriteInt((uint)house.Position.Y); - pak.WriteShort((ushort)house.Heading); //useless/ignored by client. + pak.WriteShort((ushort)house.Orientation); //useless/ignored by client. pak.WriteByte(0x00); pak.WriteByte((byte)(house.GetGuildEmblemFlags() | (house.Emblem & 0x010000) >> 14));//new Guild Emblem pak.WriteShort((ushort)house.Emblem); //emblem diff --git a/GameServer/packets/Server/PacketLib190.cs b/GameServer/packets/Server/PacketLib190.cs index fa932004..8d66e27c 100644 --- a/GameServer/packets/Server/PacketLib190.cs +++ b/GameServer/packets/Server/PacketLib190.cs @@ -246,7 +246,7 @@ public override void SendPlayerForgedPosition(GamePlayer player) // Write Speed if (player.Steed != null && player.Steed.ObjectState == GameObject.eObjectState.Active) { - player.Heading = player.Steed.Heading; + player.Orientation = player.Steed.Orientation; pak.WriteShort(0x1800); } else @@ -291,12 +291,10 @@ public override void SendPlayerForgedPosition(GamePlayer player) } // Get Off Corrd - var offX = player.Position.X - player.CurrentZone.XOffset; - var offY = player.Position.Y - player.CurrentZone.YOffset; - - pak.WriteShort((ushort)player.Position.Z); - pak.WriteShort((ushort)offX); - pak.WriteShort((ushort)offY); + var zoneCoord = player.Coordinate - player.CurrentZone.Offset; + pak.WriteShort((ushort)zoneCoord.Z); + pak.WriteShort((ushort)zoneCoord.X); + pak.WriteShort((ushort)zoneCoord.Y); // Write Zone pak.WriteShort(player.CurrentZone.ZoneSkinID); @@ -310,7 +308,7 @@ public override void SendPlayerForgedPosition(GamePlayer player) else { // Set Player always on ground, this is an "anti lag" packet - ushort contenthead = (ushort)(player.Heading + (true ? 0x1000 : 0)); + ushort contenthead = (ushort)(player.Orientation.InHeading + (true ? 0x1000 : 0)); pak.WriteShort(contenthead); // No Fall Speed. pak.WriteShort(0); diff --git a/GameServer/packets/Server/PacketLib199.cs b/GameServer/packets/Server/PacketLib199.cs index ff1dd3f0..2a4092e4 100644 --- a/GameServer/packets/Server/PacketLib199.cs +++ b/GameServer/packets/Server/PacketLib199.cs @@ -22,6 +22,7 @@ using System.Reflection; using DOL.Database; +using DOL.GS.Geometry; using DOL.Language; using log4net; @@ -116,7 +117,8 @@ public override void SendCharacterOverview(eRealm realm) Region reg = WorldMgr.GetRegion((ushort)characters[j].Region); if (reg != null) { - var description = m_gameClient.GetTranslatedSpotDescription(reg, characters[j].Xpos, characters[j].Ypos, characters[j].Zpos); + var coordinate = characters[j].GetPosition().Coordinate; + var description = GamePlayerUtils.GetTranslatedSpotDescription(reg, m_gameClient, coordinate); pak.FillString(description, 24); } else diff --git a/GameServer/quests/Tasks/KillTask.cs b/GameServer/quests/Tasks/KillTask.cs index 2c9d19a1..987b391d 100644 --- a/GameServer/quests/Tasks/KillTask.cs +++ b/GameServer/quests/Tasks/KillTask.cs @@ -22,6 +22,7 @@ using DOL.Database; using DOL.Events; using DOL.GS.PacketHandler; +using DOL.Language; namespace DOL.GS.Quests { @@ -245,7 +246,6 @@ public override void Notify(DOLEvent e, object sender, EventArgs args) droppeditem.Name = itemdrop.Name; droppeditem.Level = 1; droppeditem.Position = target.Position; - droppeditem.CurrentRegion = target.CurrentRegion; droppeditem.AddToWorld(); if (dropMessages.Count > 0) { @@ -320,33 +320,11 @@ public static bool BuildTask(GamePlayer player, GameLiving source) ((KillTask)player.Task).ItemIndex = Util.Random(0, TaskObjects.Length - 1); ((KillTask)player.Task).MobName = Mob.Name; player.Task.RecieverName = source.Name; - player.Out.SendMessage(source.Name + " says, *Very well " + player.Name + ", it's good to see adventurers willing to help out the realm in such times. Search to the " + GetDirectionFromHeading(Mob.Heading) + " and kill a " + Mob.Name + " and return to me for your reward. Good luck!*", eChatType.CT_System, eChatLoc.CL_SystemWindow); + player.Out.SendMessage(source.Name + " says, *Very well " + player.Name + ", it's good to see adventurers willing to help out the realm in such times. Search to the " + LanguageMgr.GetCardinalDirection(player.Client.Account.Language, Mob.Orientation) + " and kill a " + Mob.Name + " and return to me for your reward. Good luck!*", eChatType.CT_System, eChatLoc.CL_SystemWindow); player.Out.SendDialogBox(eDialogCode.SimpleWarning, 1, 1, 1, 1, eDialogType.Ok, false, "You have been given a task!"); return true; } } - public static string GetDirectionFromHeading(ushort heading) - { - if (heading < 0) - heading += 4096; - if (heading >= 3840 || heading <= 256) - return "South"; - else if (heading > 256 && heading < 768) - return "South West"; - else if (heading >= 768 && heading <= 1280) - return "West"; - else if (heading > 1280 && heading < 1792) - return "North West"; - else if (heading >= 1792 && heading <= 2304) - return "North"; - else if (heading > 2304 && heading < 2816) - return "North East"; - else if (heading >= 2816 && heading <= 3328) - return "East"; - else if (heading > 3328 && heading < 3840) - return "South East"; - return ""; - } /// /// Find a Random Mob in Radius Distance diff --git a/GameServer/realmabilities/Statics/GenericBase.cs b/GameServer/realmabilities/Statics/GenericBase.cs index 4349719b..306d58bd 100644 --- a/GameServer/realmabilities/Statics/GenericBase.cs +++ b/GameServer/realmabilities/Statics/GenericBase.cs @@ -3,6 +3,7 @@ using DOL.GS; using DOL.GS.Spells; using DOL.Events; +using DOL.GS.Geometry; using DOL.GS.PacketHandler; using System.Numerics; @@ -19,26 +20,26 @@ public abstract class GenericBase : GameStaticItem protected uint m_pulseFrequency; int currentTick = 0; int currentPulse = 0; - protected int getCurrentPulse() - { return currentPulse; } + protected int getCurrentPulse () + {return currentPulse;} - public void CreateStatic(GamePlayer caster, Vector3 gt, uint lifeTime, uint pulseFrequency, ushort radius) + public void CreateStatic(GamePlayer caster, Coordinate gt, uint lifeTime, uint pulseFrequency, ushort radius) { - m_lifeTime = lifeTime; - m_caster = caster; - m_radius = radius; - m_pulseFrequency = pulseFrequency; - this.Name = GetStaticName(); - this.Model = GetStaticModel(); - this.Position = gt; - this.CurrentRegionID = m_caster.CurrentRegionID; - this.Level = caster.Level; + m_lifeTime = lifeTime; + m_caster = caster; + m_radius = radius; + m_pulseFrequency = pulseFrequency; + this.Name = GetStaticName(); + this.Model = GetStaticModel(); + Position = caster.Position.With(coordinate: gt); + this.Level = caster.Level; this.Realm = caster.Realm; this.AddToWorld(); - } - public override bool AddToWorld() + } + + public override bool AddToWorld() { - new RegionTimer(this, new RegionTimerCallback(PulseTimer), 1000); + new RegionTimer(this, new RegionTimerCallback(PulseTimer),1000); GameEventMgr.AddHandler(m_caster, GamePlayerEvent.RemoveFromWorld, new DOLEventHandler(PlayerLeftWorld)); return base.AddToWorld(); } diff --git a/GameServer/realmabilities/effects/rr5/BoilingCauldronEffect.cs b/GameServer/realmabilities/effects/rr5/BoilingCauldronEffect.cs index 27ecb7d4..d2086935 100644 --- a/GameServer/realmabilities/effects/rr5/BoilingCauldronEffect.cs +++ b/GameServer/realmabilities/effects/rr5/BoilingCauldronEffect.cs @@ -70,13 +70,11 @@ public override void Stop() private void SummonCauldron() { Cauldron = new GameStaticItem(); - Cauldron.CurrentRegion = EffectOwner.CurrentRegion; - Cauldron.Heading = (ushort)((EffectOwner.Heading + 2048) % 4096); Cauldron.Level = cauldronLevel; Cauldron.Realm = EffectOwner.Realm; Cauldron.Name = cauldronName; Cauldron.Model = cauldronModel; - Cauldron.Position = EffectOwner.Position; + Cauldron.Position = EffectOwner.Position.TurnedAround(); Cauldron.AddToWorld(); new RegionTimer(EffectOwner, new RegionTimerCallback(CauldronCallBack), RealmAbilities.BoilingCauldronAbility.DURATION - 1000); diff --git a/GameServer/realmabilities/effects/rr5/MinionRescueEffect.cs b/GameServer/realmabilities/effects/rr5/MinionRescueEffect.cs index fbefd19b..7e88b4d7 100644 --- a/GameServer/realmabilities/effects/rr5/MinionRescueEffect.cs +++ b/GameServer/realmabilities/effects/rr5/MinionRescueEffect.cs @@ -23,10 +23,11 @@ using DOL.AI.Brain; using DOL.Events; using DOL.Database; +using DOL.Geometry; +using DOL.GS.Geometry; using DOL.GS.PacketHandler; using DOL.GS.RealmAbilities; using DOL.GS.Spells; -using System.Numerics; namespace DOL.GS.Effects { @@ -117,8 +118,6 @@ public override void Stop() private void SummonSpirit(int spiritId, GamePlayer targetPlayer) { spirits[spiritId] = new GameNPC(); - spirits[spiritId].CurrentRegion = EffectOwner.CurrentRegion; - spirits[spiritId].Heading = (ushort)((EffectOwner.Heading + 2048) % 4096); spirits[spiritId].Level = spiritLevel; spirits[spiritId].Realm = EffectOwner.Realm; spirits[spiritId].Name = spiritName; @@ -126,8 +125,8 @@ private void SummonSpirit(int spiritId, GamePlayer targetPlayer) spirits[spiritId].MaxSpeedBase = spiritSpeed; spirits[spiritId].GuildName = ""; spirits[spiritId].Size = 50; - var rand = new Vector3(Util.Random(20, 40) - Util.Random(20, 40), Util.Random(20, 40) - Util.Random(20, 40), 0); - spirits[spiritId].Position = EffectOwner.Position + rand; + spirits[spiritId].Position = EffectOwner.Position.TurnedAround() + + Vector.Create(x: Util.Random(-20, 20), y: Util.Random(-20, 20)); spirits[spiritId].Flags |= GameNPC.eFlags.DONTSHOWNAME; spirits[spiritId].SetOwnBrain(new StandardMobBrain()); spirits[spiritId].AddToWorld(); diff --git a/GameServer/realmabilities/handlers/DecimationTrap.cs b/GameServer/realmabilities/handlers/DecimationTrap.cs index 2501c6f1..221942ea 100644 --- a/GameServer/realmabilities/handlers/DecimationTrap.cs +++ b/GameServer/realmabilities/handlers/DecimationTrap.cs @@ -4,6 +4,7 @@ using DOL.GS.Effects; using DOL.GS.PacketHandler; using DOL.Events; +using DOL.GS.Geometry; using System.Numerics; namespace DOL.GS.RealmAbilities @@ -59,12 +60,11 @@ public override void Execute(GameLiving living) } } - if (living.GroundTarget == null) + if (living.GroundTargetPosition == Position.Nowhere) return; - if (!living.IsWithinRadius(living.GroundTarget.Value, 1500)) + if (living.Coordinate.DistanceTo(living.GroundTargetPosition) > 1500 ) return; - GamePlayer player = living as GamePlayer; - if (player == null) + if (living is not GamePlayer player) return; if (player.RealmAbilityCastTimer != null) @@ -92,7 +92,7 @@ private int startSpell(RegionTimer timer) if (!owner.IsAlive) return 0; - traparea = new Area.Circle("decimation trap", owner.Position, 50); + traparea = new Area.Circle("decimation trap", owner.Coordinate, 50); owner.CurrentRegion.AddArea(traparea); region = owner.CurrentRegionID; @@ -136,14 +136,14 @@ private void removeHandlers() private void getTargets() { - foreach (GamePlayer target in WorldMgr.GetPlayersCloseToSpot(region, traparea.Position, 350)) + foreach (GamePlayer target in WorldMgr.GetPlayersCloseToSpot(Position.Create(region, traparea.Coordinate), 350)) { if (GameServer.ServerRules.IsAllowedToAttack(owner, target, true)) { DamageTarget(target); } } - foreach (GameNPC target in WorldMgr.GetNPCsCloseToSpot(region, traparea.Position, 350)) + foreach (GameNPC target in WorldMgr.GetNPCsCloseToSpot(Position.Create(region, traparea.Coordinate), 350)) { if (GameServer.ServerRules.IsAllowedToAttack(owner, target, true)) { @@ -163,7 +163,7 @@ private void DamageTarget(GameLiving target) ticktimer.Stop(); removeHandlers(); } - var dist = Vector3.Distance(target.Position, traparea.Position); + var dist = (int)target.Coordinate.DistanceTo(traparea.Coordinate); double mod = 1; if (dist > 0) mod = 1 - ((double)dist / 350); diff --git a/GameServer/realmabilities/handlers/NegativeMaelstromAbility.cs b/GameServer/realmabilities/handlers/NegativeMaelstromAbility.cs index 840f3cb4..6e1611ce 100644 --- a/GameServer/realmabilities/handlers/NegativeMaelstromAbility.cs +++ b/GameServer/realmabilities/handlers/NegativeMaelstromAbility.cs @@ -6,6 +6,7 @@ using DOL.GS.Effects; using DOL.Events; using DOL.Database; +using DOL.GS.Geometry; namespace DOL.GS.RealmAbilities { @@ -28,7 +29,7 @@ public override void Execute(GameLiving living) return; } - if (caster.GroundTarget == null || !caster.IsWithinRadius(caster.GroundTarget.Value, 1500)) + if (caster.GroundTargetPosition == Position.Nowhere || !caster.IsWithinRadius(caster.GroundTargetPosition, 1500)) { caster.Out.SendMessage("You groundtarget is too far away to use this ability!", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; diff --git a/GameServer/realmabilities/handlers/PerfectRecoveryAbility.cs b/GameServer/realmabilities/handlers/PerfectRecoveryAbility.cs index 70b4b65a..5bba1e81 100644 --- a/GameServer/realmabilities/handlers/PerfectRecoveryAbility.cs +++ b/GameServer/realmabilities/handlers/PerfectRecoveryAbility.cs @@ -183,7 +183,7 @@ public void ResurrectLiving(GamePlayer resurrectedPlayer, GameLiving rezzer) resurrectedPlayer.Health = (int)(resurrectedPlayer.MaxHealth * m_resurrectValue / 100); resurrectedPlayer.Mana = (int)(resurrectedPlayer.MaxMana * m_resurrectValue / 100); resurrectedPlayer.Endurance = (int)(resurrectedPlayer.MaxEndurance * m_resurrectValue / 100); //no endurance after any rez - resurrectedPlayer.MoveTo(rezzer.CurrentRegionID, rezzer.Position, rezzer.Heading); + resurrectedPlayer.MoveTo(rezzer.Position); GameLiving living = resurrectedPlayer as GameLiving; GameTimer resurrectExpiredTimer = null; diff --git a/GameServer/realmabilities/handlers/StaticTempestAbility.cs b/GameServer/realmabilities/handlers/StaticTempestAbility.cs index 0c64be1c..b4bfa8da 100644 --- a/GameServer/realmabilities/handlers/StaticTempestAbility.cs +++ b/GameServer/realmabilities/handlers/StaticTempestAbility.cs @@ -78,7 +78,7 @@ public override void Execute(GameLiving living) } } Statics.StaticTempestBase st = new Statics.StaticTempestBase(m_stunDuration); - st.CreateStatic(caster, caster.TargetObject.Position, m_duration, 5, 360); + st.CreateStatic(caster, caster.TargetObject.Coordinate, m_duration, 5, 360); DisableSkill(living); } public override int GetReUseDelay(int level) diff --git a/GameServer/realmabilities/handlers/ThornweedFieldAbility.cs b/GameServer/realmabilities/handlers/ThornweedFieldAbility.cs index 31b13c06..65032a0e 100644 --- a/GameServer/realmabilities/handlers/ThornweedFieldAbility.cs +++ b/GameServer/realmabilities/handlers/ThornweedFieldAbility.cs @@ -6,6 +6,7 @@ using DOL.GS.Effects; using DOL.Events; using DOL.Database; +using DOL.GS.Geometry; namespace DOL.GS.RealmAbilities { @@ -30,12 +31,12 @@ public override void Execute(GameLiving living) return; } - if (caster.GroundTarget == null) + if (caster.GroundTargetPosition == Position.Nowhere) { caster.Out.SendMessage("You must set a ground target to use this ability!", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } - else if (!caster.IsWithinRadius(caster.GroundTarget.Value, 1500)) + else if (!caster.IsWithinRadius(caster.GroundTargetPosition, 1500)) { caster.Out.SendMessage("Your ground target is too far away to use this ability!", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; diff --git a/GameServer/realmabilities/handlers/rr5/WallOfFlameAbility.cs b/GameServer/realmabilities/handlers/rr5/WallOfFlameAbility.cs index 94f4fdf3..704c789c 100644 --- a/GameServer/realmabilities/handlers/rr5/WallOfFlameAbility.cs +++ b/GameServer/realmabilities/handlers/rr5/WallOfFlameAbility.cs @@ -47,7 +47,7 @@ public override void Execute(GameLiving living) } Statics.WallOfFlameBase wof = new Statics.WallOfFlameBase(dmgValue); - wof.CreateStatic(caster, caster.Position, duration, 3, 150); + wof.CreateStatic(caster, caster.Coordinate, duration, 3, 150); DisableSkill(living); caster.StopCurrentSpellcast(); diff --git a/GameServer/relics/RelicPad.cs b/GameServer/relics/RelicPad.cs index 5737d120..936c0731 100644 --- a/GameServer/relics/RelicPad.cs +++ b/GameServer/relics/RelicPad.cs @@ -95,7 +95,7 @@ public class Surface : Area.Circle private RelicPad m_relicPad; public Surface(RelicPad relicPad) - : base("", relicPad.Position, RelicPad.Radius) + : base("", relicPad.Coordinate, RelicPad.Radius) { m_relicPad = relicPad; } diff --git a/GameServer/serverrules/AbstractServerRules.cs b/GameServer/serverrules/AbstractServerRules.cs index f8576914..bb34bd71 100644 --- a/GameServer/serverrules/AbstractServerRules.cs +++ b/GameServer/serverrules/AbstractServerRules.cs @@ -28,6 +28,7 @@ using DOL.Events; using DOL.gameobjects.CustomNPC; using DOL.GS.Finance; +using DOL.GS.Geometry; using DOL.GS.Housing; using DOL.GS.Keeps; using DOL.GS.PacketHandler; @@ -252,16 +253,22 @@ public virtual void OnReleased(DOLEvent e, object sender, EventArgs args) GamePlayer player = (GamePlayer)sender; StartImmunityTimer(player, ServerProperties.Properties.TIMER_KILLED_BY_MOB * 1000);//When Killed by a Mob } - + /// /// Should be called whenever a player teleports to a new location /// /// /// /// + public virtual void OnPlayerTeleport(GamePlayer player, Teleport destination) + { + } + + [Obsolete("Use .OnPlayerTeleport(GamePlayer,Teleport) instead!")] + public virtual void OnPlayerTeleport(GamePlayer player, GameLocation source, Teleport destination) { - // override this in order to do something, like set immunity, when a player teleports + OnPlayerTeleport(player, destination); } /// @@ -1443,7 +1450,7 @@ and it will also let higher level players (the 35-50s who tend to hit this clamp if (player != null) { AbstractGameKeep keep = - GameServer.KeepManager.GetKeepCloseToSpot(living.CurrentRegionID, living.Position, 16000); + GameServer.KeepManager.GetKeepCloseToSpot(living.Position, 16000); if (keep != null) { byte bonus = 0; @@ -1801,7 +1808,7 @@ public virtual void OnPlayerKilled(GamePlayer killedPlayer, GameObject killer) if (!BG && living is GamePlayer) { - AbstractGameKeep keep = GameServer.KeepManager.GetKeepCloseToSpot(living.CurrentRegionID, living.Position, 16000); + AbstractGameKeep keep = GameServer.KeepManager.GetKeepCloseToSpot(living.Position, 16000); if (keep != null) { byte bonus = 0; @@ -2368,16 +2375,15 @@ public virtual void BuyHousingItem(GamePlayer player, ushort slot, byte count, D GameMerchant.OnPlayerBuy(player, slot, count, items); } + [Obsolete("Use .PlaceHousingNPC(House, ItemTemplate, Coordinate, ushort) instead!")] + public virtual GameNPC PlaceHousingNPC(DOL.GS.Housing.House house, ItemTemplate item, Vector3 location, ushort heading) + => PlaceHousingNPC(house, item, Coordinate.Create((int)location.X, (int)location.Y, (int)location.Z), heading); /// /// Get a housing hookpoint NPC /// - /// - /// - /// - /// /// - public virtual GameNPC PlaceHousingNPC(DOL.GS.Housing.House house, ItemTemplate item, Vector3 location, ushort heading) + public virtual GameNPC PlaceHousingNPC(DOL.GS.Housing.House house, ItemTemplate item, Coordinate coordinate, ushort heading) { NpcTemplate npcTemplate = NpcTemplateMgr.GetTemplate(item.Bonus); @@ -2446,9 +2452,7 @@ public virtual GameNPC PlaceHousingNPC(DOL.GS.Housing.House house, ItemTemplate npc.Name = item.Name; npc.CurrentHouse = house; npc.OwnerID = item.Id_nb; - npc.Position = location; - npc.Heading = heading; - npc.CurrentRegionID = house.RegionID; + npc.Position = Position.Create(house.RegionID, coordinate, heading); if (!npc.IsPeaceful) { npc.Flags ^= GameNPC.eFlags.PEACE; @@ -2464,15 +2468,16 @@ public virtual GameNPC PlaceHousingNPC(DOL.GS.Housing.House house, ItemTemplate return null; } - + [Obsolete("Use .PlaceHousingInteriorItem(House, ItemTemplate, Coordinate, ushort) instead!")] public virtual GameStaticItem PlaceHousingInteriorItem(DOL.GS.Housing.House house, ItemTemplate item, Vector3 location, ushort heading) + => PlaceHousingInteriorItem(house, item, Coordinate.Create((int)location.X, (int)location.Y, (int)location.Z), heading); + + public virtual GameStaticItem PlaceHousingInteriorItem(DOL.GS.Housing.House house, ItemTemplate item, Coordinate coordinate, ushort heading) { GameStaticItem hookpointObject = new GameStaticItem(); hookpointObject.CurrentHouse = house; hookpointObject.OwnerID = item.Id_nb; - hookpointObject.Position = location; - hookpointObject.Heading = heading; - hookpointObject.CurrentRegionID = house.RegionID; + hookpointObject.Position = Position.Create(house.RegionID, coordinate, heading); hookpointObject.Name = item.Name; hookpointObject.Model = (ushort)item.Model; hookpointObject.AddToWorld(); diff --git a/GameServer/serverrules/AdventureWingJumpPoint.cs b/GameServer/serverrules/AdventureWingJumpPoint.cs index 4ec21a03..c9bb64d5 100644 --- a/GameServer/serverrules/AdventureWingJumpPoint.cs +++ b/GameServer/serverrules/AdventureWingJumpPoint.cs @@ -18,6 +18,7 @@ */ using DOL.Database; +using DOL.GS.Geometry; using DOL.GS.PacketHandler; using System.Collections; using System.Collections.Generic; @@ -46,7 +47,7 @@ public bool IsAllowedToJump(ZonePoint targetPoint, GamePlayer player) { //Handles zoning INTO an instance. - GameLocation loc = null; + Position position = Position.Nowhere; AdventureWingInstance previousInstance = null; // Do we have a group ? @@ -116,11 +117,6 @@ public bool IsAllowedToJump(ZonePoint targetPoint, GamePlayer player) { // I have no instance to go to, create one ! previousInstance = (AdventureWingInstance)WorldMgr.CreateInstance(targetPoint.TargetRegion, typeof(AdventureWingInstance)); - if (targetPoint.SourceRegion != 0 && targetPoint.SourceRegion == player.CurrentRegionID) - { - //source loc seems legit... - previousInstance.SourceEntrance = new GameLocation("source", targetPoint.SourceRegion, targetPoint.SourceX, targetPoint.SourceY, targetPoint.SourceZ); - } if (player.Group != null) { @@ -192,18 +188,12 @@ public bool IsAllowedToJump(ZonePoint targetPoint, GamePlayer player) } - //get loc of instance - if (previousInstance != null) - { - loc = new GameLocation(previousInstance.Description + " (instance)", previousInstance.ID, targetPoint.TargetX, targetPoint.TargetY, targetPoint.TargetZ, targetPoint.TargetHeading); - } - - - if (loc != null) + position = targetPoint.GetTargetPosition().With(regionID: previousInstance.ID); + if (position != Position.Nowhere) { // Move Player, changing target destination is failing !! - player.MoveTo(loc); + player.MoveTo(position); return false; } diff --git a/GameServer/serverrules/IServerRules.cs b/GameServer/serverrules/IServerRules.cs index 13127a6a..251010a1 100644 --- a/GameServer/serverrules/IServerRules.cs +++ b/GameServer/serverrules/IServerRules.cs @@ -24,6 +24,7 @@ using DOL.GS.Keeps; using System.Numerics; using AmteScripts.Managers; +using DOL.GS.Geometry; using System.Linq; namespace DOL.GS.ServerRules @@ -292,9 +293,9 @@ public interface IServerRules /// /// Invoked when a player teleports somewhere /// - /// - /// - /// + void OnPlayerTeleport(GamePlayer player, Teleport destination); + + [Obsolete("Use .OnPlayerTeleport(GamePlayer,Teleport) instead!")] void OnPlayerTeleport(GamePlayer player, GameLocation source, Teleport destination); /// @@ -494,21 +495,18 @@ public interface IServerRules /// /// Get a housing hookpoint NPC /// - /// - /// - /// - /// /// + GameNPC PlaceHousingNPC(DOL.GS.Housing.House house, ItemTemplate item, Coordinate coordinate, ushort heading); + + [Obsolete("Use .PlayerHousingNPC(House,ItemTemplate,Coordinate,ushort) instead!")] GameNPC PlaceHousingNPC(DOL.GS.Housing.House house, ItemTemplate item, Vector3 location, ushort heading); /// /// Get a static interior object for a house hookpoint /// - /// - /// - /// - /// /// + GameStaticItem PlaceHousingInteriorItem(DOL.GS.Housing.House house, ItemTemplate item, Coordinate coordinate, ushort heading); + [Obsolete("Use .PlaceHousingInteriorItem(House,ItemTemplate,Coordinate,ushort) instead!")] GameStaticItem PlaceHousingInteriorItem(DOL.GS.Housing.House house, ItemTemplate item, Vector3 location, ushort heading); /// diff --git a/GameServer/serverrules/PvPServerRules.cs b/GameServer/serverrules/PvPServerRules.cs index 29a9d1d3..cbc10685 100644 --- a/GameServer/serverrules/PvPServerRules.cs +++ b/GameServer/serverrules/PvPServerRules.cs @@ -109,11 +109,11 @@ public override void OnReleased(DOLEvent e, object sender, EventArgs args) /// /// /// - public override void OnPlayerTeleport(GamePlayer player, GameLocation source, Teleport destination) + public override void OnPlayerTeleport(GamePlayer player, Teleport destination) { // Since region change already starts an immunity timer we only want to do this if a player // is teleporting within the same region - if (source.RegionID == destination.RegionID) + if (player.CurrentRegionID == destination.RegionID) { StartImmunityTimer(player, ServerProperties.Properties.TIMER_PVP_TELEPORT * 1000); } @@ -135,7 +135,7 @@ public override void OnPlayerTeleport(GamePlayer player, GameLocation source, Te //No PVP Dungeons: http://support.darkageofcamelot.com/cgi-bin/support.cfg/php/enduser/std_adp.php?p_sid=frxnPUjg&p_lva=&p_refno=020709-000000&p_created=1026248996&p_sp=cF9ncmlkc29ydD0mcF9yb3dfY250PTE0JnBfc2VhcmNoX3RleHQ9JnBfc2VhcmNoX3R5cGU9MyZwX2NhdF9sdmwxPTI2JnBfY2F0X2x2bDI9fmFueX4mcF9zb3J0X2J5PWRmbHQmcF9wYWdlPTE*&p_li 21, //Tomb of Mithra - 129, //Nisse�s Lair (Nisee's Lair in regions.ini) + 129, //Nisse's Lair (Nisse's Lair in regions.ini) 221, //Muire Tomb (Undead in regions.ini) }; diff --git a/GameServer/serverrules/TaskDungeonJumpPoint.cs b/GameServer/serverrules/TaskDungeonJumpPoint.cs index f00bd376..3beabf9d 100644 --- a/GameServer/serverrules/TaskDungeonJumpPoint.cs +++ b/GameServer/serverrules/TaskDungeonJumpPoint.cs @@ -18,6 +18,7 @@ */ using DOL.Database; +using DOL.GS.Geometry; using DOL.GS.PacketHandler; using DOL.GS.Quests; @@ -39,7 +40,7 @@ public class TaskDungeonJumpPoint : IJumpPointHandler public bool IsAllowedToJump(ZonePoint targetPoint, GamePlayer player) { //Handles zoning INTO an instance. - GameLocation loc = null; + var loc = Position.Nowhere; //First, we try the groups mission. if (player.Group != null) @@ -49,23 +50,23 @@ public bool IsAllowedToJump(ZonePoint targetPoint, GamePlayer player) { //Attempt to get the instance entrance location... TaskDungeonMission task = (TaskDungeonMission)grp.Mission; - loc = task.TaskRegion.InstanceEntranceLocation; + loc = task.TaskRegion.EntrancePosition; } } else if (player.Mission != null && player.Mission is TaskDungeonMission) { //Then, try personal missions... TaskDungeonMission task = (TaskDungeonMission)player.Mission; - loc = task.TaskRegion.InstanceEntranceLocation; + loc = task.TaskRegion.EntrancePosition; } - if (loc != null) + if (loc != Position.Nowhere) { - targetPoint.TargetX = (int)loc.Position.X; - targetPoint.TargetY = (int)loc.Position.Y; - targetPoint.TargetZ = (int)loc.Position.Z; + targetPoint.TargetX = loc.X; + targetPoint.TargetY = loc.Y; + targetPoint.TargetZ = loc.Z; targetPoint.TargetRegion = loc.RegionID; - targetPoint.TargetHeading = loc.Heading; + targetPoint.TargetHeading = loc.Orientation.InHeading; return true; } diff --git a/GameServer/spells/Animist/SummonAnimistFnF.cs b/GameServer/spells/Animist/SummonAnimistFnF.cs index d924e877..6d03706e 100644 --- a/GameServer/spells/Animist/SummonAnimistFnF.cs +++ b/GameServer/spells/Animist/SummonAnimistFnF.cs @@ -37,14 +37,14 @@ public override bool CheckBeginCast(GameLiving selectedTarget) Region rgn = WorldMgr.GetRegion(Caster.CurrentRegion.ID); - if (rgn == null || rgn.GetZone(Caster.GroundTarget.Value) == null) + if (rgn == null || rgn.GetZone(Caster.GroundTargetPosition.Coordinate) == null) { if (Caster is GamePlayer) MessageToCaster(LanguageMgr.GetTranslation((Caster as GamePlayer).Client, "SummonAnimistFnF.CheckBeginCast.NoGroundTarget"), eChatType.CT_SpellResisted); return false; } - foreach (GameNPC npc in Caster.CurrentRegion.GetNPCsInRadius(Caster.GroundTarget.Value, (ushort)Properties.TURRET_AREA_CAP_RADIUS, false, true)) + foreach (GameNPC npc in Caster.CurrentRegion.GetNPCsInRadius(Caster.GroundTargetCoordinate.Coordinate, (ushort)Properties.TURRET_AREA_CAP_RADIUS, false, true)) if (npc.Brain is TurretFNFBrain) nCount++; diff --git a/GameServer/spells/Animist/SummonAnimistPet.cs b/GameServer/spells/Animist/SummonAnimistPet.cs index 8203e333..1c859bce 100644 --- a/GameServer/spells/Animist/SummonAnimistPet.cs +++ b/GameServer/spells/Animist/SummonAnimistPet.cs @@ -17,6 +17,7 @@ * */ using DOL.AI.Brain; +using DOL.GS.Geometry; using DOL.GS.PacketHandler; using DOL.Language; using System.Numerics; @@ -30,7 +31,7 @@ protected SummonAnimistPet(GameLiving caster, Spell spell, SpellLine line) public override bool CheckBeginCast(GameLiving selectedTarget) { - if (Caster.GroundTarget == null) + if (Caster.GroundTargetPosition == Position.Nowhere) { if (Caster is GamePlayer) MessageToCaster(LanguageMgr.GetTranslation((Caster as GamePlayer).Client, "SummonAnimistPet.CheckBeginCast.GroundTargetNull"), eChatType.CT_SpellResisted); @@ -44,7 +45,7 @@ public override bool CheckBeginCast(GameLiving selectedTarget) return false; } - if (!Caster.IsWithinRadius(Caster.GroundTarget.Value, CalculateSpellRange())) + if (!Caster.IsWithinRadius(Caster.GroundTargetPosition, CalculateSpellRange())) { if (Caster is GamePlayer) MessageToCaster(LanguageMgr.GetTranslation((Caster as GamePlayer).Client, "SummonAnimistPet.CheckBeginCast.GroundTargetNotInSpellRange"), eChatType.CT_SpellResisted); @@ -55,7 +56,7 @@ public override bool CheckBeginCast(GameLiving selectedTarget) } public override void FinishSpellCast(GameLiving target) { - if (Caster.GroundTarget == null) + if (Caster.GroundTargetPosition == Position.Nowhere) { if (Caster is GamePlayer) MessageToCaster(LanguageMgr.GetTranslation((Caster as GamePlayer).Client, "SummonAnimistPet.CheckBeginCast.GroundTargetNull"), eChatType.CT_SpellResisted); @@ -76,7 +77,7 @@ public override void FinishSpellCast(GameLiving target) return; } - if (!Caster.IsWithinRadius(Caster.GroundTarget.Value, CalculateSpellRange())) + if (!Caster.IsWithinRadius(Caster.GroundTargetPosition, CalculateSpellRange())) { if (Caster is GamePlayer) MessageToCaster(LanguageMgr.GetTranslation((Caster as GamePlayer).Client, "SummonAnimistPet.CheckBeginCast.GroundTargetNotInSpellRange"), eChatType.CT_SpellResisted); @@ -112,12 +113,8 @@ protected override IControlledBrain GetPetBrain(GameLiving owner) return new TurretBrain(owner); } - protected override void GetPetLocation(out Vector3 pos, out ushort heading, out Region region) - { - pos = Caster.GroundTarget.Value; - heading = Caster.Heading; - region = Caster.CurrentRegion; - } + protected override Position GetSummonPosition() + => Caster.GroundTargetPosition; /// /// Do not trigger SubSpells diff --git a/GameServer/spells/Animist/TurretSpellHandler.cs b/GameServer/spells/Animist/TurretSpellHandler.cs index 753dc543..4507b427 100644 --- a/GameServer/spells/Animist/TurretSpellHandler.cs +++ b/GameServer/spells/Animist/TurretSpellHandler.cs @@ -74,7 +74,7 @@ public override void ApplyEffectOnTarget(GameLiving target, double effectiveness { if (target != null && target.CurrentRegion != null) { - foreach (GameNPC npc in target.CurrentRegion.GetNPCsInRadius(target.Position, (ushort)Spell.Radius, false, true)) + foreach (GameNPC npc in target.CurrentRegion.GetNPCsInRadius(target.Coordinate, (ushort)Spell.Radius, false, true)) { if (npc == null || !npc.IsAlive) { diff --git a/GameServer/spells/Archery/Archery.cs b/GameServer/spells/Archery/Archery.cs index 727d0a50..25b02684 100644 --- a/GameServer/spells/Archery/Archery.cs +++ b/GameServer/spells/Archery/Archery.cs @@ -107,7 +107,7 @@ public override bool CheckBeginCast(GameLiving selectedTarget) String targetType = m_spell.Target.ToLower(); if (targetType == "area") { - if (!m_caster.IsWithinRadius(m_caster.GroundTarget.Value, CalculateSpellRange())) + if (!m_caster.IsWithinRadius(m_caster.GroundTargetPosition, CalculateSpellRange())) { MessageToCaster("Your area target is out of range. Select a closer target.", eChatType.CT_SpellResisted); return false; @@ -309,7 +309,7 @@ public override void FinishSpellCast(GameLiving target) Caster.LastAttackTickPvE = Caster.CurrentRegion.Time; Caster.LastAttackTickPvP = Caster.CurrentRegion.Time; - foreach (GameLiving npc in WorldMgr.GetNPCsCloseToSpot(Caster.CurrentRegionID, Caster.GroundTarget.Value, (ushort)Spell.Radius)) + foreach (GameLiving npc in WorldMgr.GetNPCsCloseToSpot(Caster.GroundTargetPosition, (ushort)Spell.Radius)) { if (npc.Realm == 0 || Caster.Realm == 0) { diff --git a/GameServer/spells/Artifacts/bracerofzo.cs b/GameServer/spells/Artifacts/bracerofzo.cs index d307080c..dc357586 100644 --- a/GameServer/spells/Artifacts/bracerofzo.cs +++ b/GameServer/spells/Artifacts/bracerofzo.cs @@ -21,7 +21,7 @@ using DOL.GS.PacketHandler; using DOL.GS.Effects; using DOL.AI.Brain; -using System.Numerics; +using DOL.GS.Geometry; namespace DOL.GS.Spells { @@ -53,16 +53,13 @@ public override void OnEffectStart(GameSpellEffect effect) return; } - Vector2 spawnPoint = Caster.GetPointFromHeading(Caster.Heading, 64); + var spawnPoint = Caster.Position.TurnedAround() + Vector.Create(Caster.Orientation, length: 64); int i = 0; - for (i = 0; i < 3; i++) - { + for(i=0;i<3;i++) + { deamons[i] = new ZoarkatPet(template); deamons[i].SetOwnBrain(new ProcPetBrain(player)); - var offset = new Vector2(Util.Random(20, 40) - Util.Random(20, 40), Util.Random(20, 40) - Util.Random(20, 40)); - deamons[i].Position = new Vector3(spawnPoint + offset, Caster.Position.Z); - deamons[i].CurrentRegion = Caster.CurrentRegion; - deamons[i].Heading = (ushort)((Caster.Heading + 2048) % 4096); + deamons[i].Position = spawnPoint + Vector.Create(x: Util.Random(-20,20), y: Util.Random(-20,20)); deamons[i].Realm = Caster.Realm; deamons[i].Level = 36; deamons[i].Flags |= GameNPC.eFlags.FLYING; diff --git a/GameServer/spells/AstralPetSummon.cs b/GameServer/spells/AstralPetSummon.cs index 5e885066..ccd58f22 100644 --- a/GameServer/spells/AstralPetSummon.cs +++ b/GameServer/spells/AstralPetSummon.cs @@ -27,8 +27,8 @@ using DOL.GS.PacketHandler; using DOL.Language; using DOL.Database; +using DOL.GS.Geometry; using DOL.GS.Styles; -using System.Numerics; namespace DOL.GS.Spells { @@ -76,11 +76,8 @@ protected override void OnNpcReleaseCommand(DOLEvent e, object sender, EventArgs effect.Cancel(false); } - protected override void GetPetLocation(out Vector3 pos, out ushort heading, out Region region) - { - base.GetPetLocation(out pos, out heading, out region); - heading = Caster.Heading; - } + protected override Position GetSummonPosition() + => Caster.Position + Vector.Create(Caster.Orientation, length: 64); public AstralPetSummon(GameLiving caster, Spell spell, SpellLine line) : base(caster, spell, line) { } diff --git a/GameServer/spells/CommonAstralSpells.cs b/GameServer/spells/CommonAstralSpells.cs index 9596ab11..2034cfc5 100644 --- a/GameServer/spells/CommonAstralSpells.cs +++ b/GameServer/spells/CommonAstralSpells.cs @@ -19,7 +19,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Numerics; using System.Reflection; using DOL.AI.Brain; @@ -27,6 +26,7 @@ using DOL.Events; using DOL.GS; using DOL.GS.Effects; +using DOL.GS.Geometry; using DOL.GS.PacketHandler; using DOL.GS.Spells; using DOL.Language; @@ -123,15 +123,13 @@ public override void ApplyEffectOnTarget(GameLiving target, double effectiveness } beffect = CreateSpellEffect(target, effectiveness); - var summonloc = GameMath.GetPointFromHeading(target, 64); + var summonPosition = target.Position.TurnedAround() + Vector.Create(target.Orientation, length: 64); BrittleBrain controlledBrain = new BrittleBrain(player); controlledBrain.IsMainPet = false; summoned = new GameNPC(template); summoned.SetOwnBrain(controlledBrain); - summoned.Position = new Vector3(summonloc, target.Position.Z); - summoned.CurrentRegion = target.CurrentRegion; - summoned.Heading = (ushort)((target.Heading + 2048) % 4096); + summoned.Position = summonPosition; summoned.Realm = target.Realm; summoned.Level = Caster.Level; summoned.Size = 50; diff --git a/GameServer/spells/EarthquakeSpellHandler.cs b/GameServer/spells/EarthquakeSpellHandler.cs index 4e3734f1..88e34b7c 100644 --- a/GameServer/spells/EarthquakeSpellHandler.cs +++ b/GameServer/spells/EarthquakeSpellHandler.cs @@ -27,7 +27,7 @@ public override bool StartSpell(GameLiving targetObject) MessageToCaster("Your spell was cancelled.", eChatType.CT_SpellExpires); return false; } - if (Caster.GroundTarget == null) + if (Caster.GroundTargetPosition == Position.Nowhere) { x = (int)Caster.Position.X; y = (int)Caster.Position.Y; @@ -81,7 +81,7 @@ public override bool StartSpell(GameLiving targetObject) if (Caster is GamePlayer player) { - int distance = (int)System.Numerics.Vector3.Distance(player.Position, new System.Numerics.Vector3(x, y, player.Position.Z)); + int distance = (int)System.Numerics.(int)player.Coordinate.DistanceTo(new System.Numerics.Vector3(x, y, player.Position.Z)); float newIntensity = intensity * (1 - distance / radius); GSTCPPacketOut pak = new GSTCPPacketOut(0x47); pak.WriteIntLowEndian(unk1); @@ -130,7 +130,7 @@ public override void OnSpellPulse(PulsingSpellEffect effect) if (Caster is GamePlayer player) { - int distance = (int)System.Numerics.Vector3.Distance(player.Position, new System.Numerics.Vector3(x, y, player.Position.Z)); + int distance = (int)System.Numerics.(int)player.Coordinate.DistanceTo(new System.Numerics.Vector3(x, y, player.Position.Z)); float newIntensity = intensity * (1 - distance / radius); GSTCPPacketOut pak = new GSTCPPacketOut(0x47); pak.WriteIntLowEndian(unk1); @@ -158,7 +158,7 @@ public override void OnSpellPulse(PulsingSpellEffect effect) public override void ApplyEffectOnTarget(GameLiving target, double effectiveness) { - int distance = (int)System.Numerics.Vector3.Distance(target.Position, new System.Numerics.Vector3(x, y, target.Position.Z)); + int distance = (int)System.Numerics.(int)target.Coordinate.DistanceTo(new System.Numerics.Vector3(x, y, target.Position.Z)); if (distance > radius) { CancelPulsingSpell(target, Spell.SpellType); diff --git a/GameServer/spells/Masterlevel/Convoker.cs b/GameServer/spells/Masterlevel/Convoker.cs index 94ccbbaf..8b9932f2 100644 --- a/GameServer/spells/Masterlevel/Convoker.cs +++ b/GameServer/spells/Masterlevel/Convoker.cs @@ -12,6 +12,8 @@ using DOL.GS.RealmAbilities; using System.Numerics; using DOL; +using DOL.GS.Geometry; +using Vector = DOL.GS.Geometry.Vector; namespace DOL.GS.Spells { @@ -62,8 +64,6 @@ public PrescienceNodeSpellHandler(GameLiving caster, Spell spell, SpellLine line font.Name = spell.Name; font.Realm = caster.Realm; font.Position = caster.Position; - font.CurrentRegionID = caster.CurrentRegionID; - font.Heading = caster.Heading; font.Owner = (GamePlayer)caster; // Construct the font spell @@ -138,8 +138,6 @@ public PowerTrapSpellHandler(GameLiving caster, Spell spell, SpellLine line) mine.Name = spell.Name; mine.Realm = caster.Realm; mine.Position = caster.Position; - mine.CurrentRegionID = caster.CurrentRegionID; - mine.Heading = caster.Heading; mine.Owner = (GamePlayer)caster; // Construct the mine spell @@ -190,8 +188,6 @@ public SpeedWrapWardSpellHandler(GameLiving caster, Spell spell, SpellLine line) font.Name = spell.Name; font.Realm = caster.Realm; font.Position = caster.Position; - font.CurrentRegionID = caster.CurrentRegionID; - font.Heading = caster.Heading; font.Owner = (GamePlayer)caster; // Construct the mine spell @@ -314,13 +310,13 @@ public override void OnEffectStart(GameSpellEffect effect) if ((effect.Owner is GamePlayer)) { GamePlayer casterPlayer = effect.Owner as GamePlayer; - if (casterPlayer.GroundTarget != null && casterPlayer.GroundTargetInView) + if (casterPlayer.GroundTargetPosition != Position.Nowhere && casterPlayer.GroundTargetInView) { GameEventMgr.AddHandler(casterPlayer, GamePlayerEvent.Moving, new DOLEventHandler(PlayerMoves)); GameEventMgr.AddHandler(warder, GameLivingEvent.Dying, new DOLEventHandler(BattleWarderDie)); GameEventMgr.AddHandler(casterPlayer, GamePlayerEvent.CastStarting, new DOLEventHandler(PlayerMoves)); GameEventMgr.AddHandler(casterPlayer, GamePlayerEvent.AttackFinished, new DOLEventHandler(PlayerMoves)); - warder.Position = casterplayer.GroundTargetPosition.Coordinate; + warder.Position = casterPlayer.GroundTargetPosition; warder.AddBrain(new MLBrain()); warder.AddToWorld(); } @@ -379,7 +375,7 @@ private void BattleWarderDie(DOLEvent e, object sender, EventArgs args) public override bool CheckBeginCast(GameLiving selectedTarget) { if (!base.CheckBeginCast(selectedTarget)) return false; - if (!(m_caster.GroundTarget != null && m_caster.GroundTargetInView)) + if (!(m_caster.GroundTargetPosition != Position.Nowhere && m_caster.GroundTargetInView)) { MessageToCaster("Your area target is out of range. Set a closer ground position.", eChatType.CT_SpellResisted); return false; @@ -393,7 +389,7 @@ public BattlewarderSpellHandler(GameLiving caster, Spell spell, SpellLine line) warder = new GameNPC(); //Fill the object variables warder.CurrentRegion = caster.CurrentRegion; - warder.Heading = (ushort)((caster.Heading + 2048) % 4096); + warder.Orientation = caster.Orientation + Angle.Degrees(180); warder.Level = 70; warder.Realm = caster.Realm; warder.Name = "Battle Warder"; @@ -423,8 +419,6 @@ public DissonanceTrapSpellHandler(GameLiving caster, Spell spell, SpellLine line mine.Name = spell.Name; mine.Realm = caster.Realm; mine.Position = caster.Position; - mine.CurrentRegionID = caster.CurrentRegionID; - mine.Heading = caster.Heading; mine.Owner = (GamePlayer)caster; // Construct the mine spell @@ -511,9 +505,7 @@ public override void ApplyEffectOnTarget(GameLiving target, double effectiveness controlledBrain.IsMainPet = false; summoned = new GameNPC(template); summoned.SetOwnBrain(controlledBrain); - summoned.Position = new Vector3(summonloc, target.Position.Z); - summoned.CurrentRegion = target.CurrentRegion; - summoned.Heading = (ushort)((target.Heading + 2048) % 4096); + summoned.Position = summoned.Position.TurnedAround() + Vector.Create(target.Orientation, length: 64); summoned.Realm = target.Realm; summoned.Level = 1; summoned.Size = 10; @@ -626,7 +618,7 @@ public class Convoker10SpellHandler : MasterlevelHandling { private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private float x, y, z; + private Position position = Position.Nowhere; GameNPC summoned = null; RegionTimer m_growTimer; private const int C_GROWTIMER = 2000; @@ -635,7 +627,7 @@ public Convoker10SpellHandler(GameLiving caster, Spell spell, SpellLine line) : public override bool CheckBeginCast(GameLiving selectedTarget) { - if (!CheckCastLocation()) + if (!CheckCastCoordinate()) return false; return base.CheckBeginCast(selectedTarget); } @@ -678,11 +670,9 @@ public override void ApplyEffectOnTarget(GameLiving target, double effectiveness summoned.SetOwnBrain(controlledBrain); //Suncheck: // Is needed, else it can cause error (i.e. /cast-command) - if (x == 0 || y == 0) - CheckCastLocation(); - summoned.Position = new Vector3(x, y, z); - summoned.CurrentRegion = player.CurrentRegion; - summoned.Heading = (ushort)((player.Heading + 2048) % 4096); + if (position == Position.Nowhere) CheckCastCoordinate(); + + summoned.Position = position.With(orientation: Caster.Orientation + Angle.Degrees(180)); summoned.Realm = player.Realm; summoned.Size = 10; summoned.Level = 100; @@ -710,22 +700,18 @@ private int TitanGrows(RegionTimer timer) return 0; } - private bool CheckCastLocation() + private bool CheckCastCoordinate() { - x = Caster.Position.X; - y = Caster.Position.Y; - z = Caster.Position.Z; + position = Caster.Position; if (Spell.Target.ToLower() == "area") { - if (Caster.GroundTargetInView && Caster.GroundTarget != null) + if (Caster.GroundTargetInView && Caster.GroundTargetPosition != Position.Nowhere) { - x = Caster.GroundTarget.Value.X; - y = Caster.GroundTarget.Value.Y; - z = Caster.GroundTarget.Value.Z; + position = Caster.GroundTargetPosition; } else { - if (Caster.GroundTarget == null) + if (Caster.GroundTargetPosition == Position.Nowhere) { MessageToCaster("You must set a groundtarget!", eChatType.CT_SpellResisted); return false; @@ -739,6 +725,7 @@ private bool CheckCastLocation() } return true; } + /// /// When an applied effect expires. /// Duration spells only. diff --git a/GameServer/spells/Masterlevel/MasterLevelBase.cs b/GameServer/spells/Masterlevel/MasterLevelBase.cs index 09d483bb..3a2e7f3a 100644 --- a/GameServer/spells/Masterlevel/MasterLevelBase.cs +++ b/GameServer/spells/Masterlevel/MasterLevelBase.cs @@ -77,7 +77,7 @@ public override IList SelectTargets(GameObject castTarget) case "area": if (Spell.Radius > 0) { - foreach (GamePlayer player in WorldMgr.GetPlayersCloseToSpot(Caster.CurrentRegionID, Caster.GroundTarget.Value, (ushort)Spell.Radius)) + foreach (GamePlayer player in WorldMgr.GetPlayersCloseToSpot(Caster.GroundTargetPosition, (ushort)Spell.Radius)) { if (GameServer.ServerRules.IsAllowedToAttack(Caster, player, true)) { @@ -280,14 +280,14 @@ public override IList SelectTargets(GameObject castTarget) case "area": if (Spell.Radius > 0) { - foreach (GamePlayer player in WorldMgr.GetPlayersCloseToSpot(Caster.CurrentRegionID, Caster.GroundTarget.Value, (ushort)Spell.Radius)) + foreach (GamePlayer player in WorldMgr.GetPlayersCloseToSpot(Caster.GroundTargetPosition, (ushort)Spell.Radius)) { if (GameServer.ServerRules.IsAllowedToAttack(Caster, player, true)) { list.Add(player); } } - foreach (GameNPC npc in WorldMgr.GetNPCsCloseToSpot(Caster.CurrentRegionID, Caster.GroundTarget.Value, (ushort)Spell.Radius)) + foreach (GameNPC npc in WorldMgr.GetNPCsCloseToSpot(Caster.GroundTargetPosition, (ushort)Spell.Radius)) { if (GameServer.ServerRules.IsAllowedToAttack(Caster, npc, true)) { @@ -469,14 +469,14 @@ public override IList SelectTargets(GameObject castTarget) case "area": if (Spell.Radius > 0) { - foreach (GamePlayer player in WorldMgr.GetPlayersCloseToSpot(Caster.CurrentRegionID, Caster.GroundTarget.Value, (ushort)Spell.Radius)) + foreach (GamePlayer player in WorldMgr.GetPlayersCloseToSpot(Caster.GroundTargetPosition, (ushort)Spell.Radius)) { if (GameServer.ServerRules.IsAllowedToAttack(Caster, player, true)) { list.Add(player); } } - foreach (GameNPC npc in WorldMgr.GetNPCsCloseToSpot(Caster.CurrentRegionID, Caster.GroundTarget.Value, (ushort)Spell.Radius)) + foreach (GameNPC npc in WorldMgr.GetNPCsCloseToSpot(Caster.GroundTargetPosition, (ushort)Spell.Radius)) { if (GameServer.ServerRules.IsAllowedToAttack(Caster, npc, true)) { @@ -658,14 +658,14 @@ public override IList SelectTargets(GameObject castTarget) case "area": if (Spell.Radius > 0) { - foreach (GamePlayer player in WorldMgr.GetPlayersCloseToSpot(Caster.CurrentRegionID, Caster.GroundTarget.Value, (ushort)Spell.Radius)) + foreach (GamePlayer player in WorldMgr.GetPlayersCloseToSpot(Caster.GroundTargetPosition, (ushort)Spell.Radius)) { if (GameServer.ServerRules.IsAllowedToAttack(Caster, player, true)) { list.Add(player); } } - foreach (GameNPC npc in WorldMgr.GetNPCsCloseToSpot(Caster.CurrentRegionID, Caster.GroundTarget.Value, (ushort)Spell.Radius)) + foreach (GameNPC npc in WorldMgr.GetNPCsCloseToSpot(Caster.GroundTargetPosition, (ushort)Spell.Radius)) { if (GameServer.ServerRules.IsAllowedToAttack(Caster, npc, true)) { @@ -875,14 +875,14 @@ public override IList SelectTargets(GameObject castTarget) case "area": if (Spell.Radius > 0) { - foreach (GamePlayer player in WorldMgr.GetPlayersCloseToSpot(Caster.CurrentRegionID, Caster.GroundTarget.Value, (ushort)Spell.Radius)) + foreach (GamePlayer player in WorldMgr.GetPlayersCloseToSpot(Caster.GroundTargetPosition, (ushort)Spell.Radius)) { if (GameServer.ServerRules.IsAllowedToAttack(Caster, player, true)) { list.Add(player); } } - foreach (GameNPC npc in WorldMgr.GetNPCsCloseToSpot(Caster.CurrentRegionID, Caster.GroundTarget.Value, (ushort)Spell.Radius)) + foreach (GameNPC npc in WorldMgr.GetNPCsCloseToSpot(Caster.GroundTargetPosition, (ushort)Spell.Radius)) { if (GameServer.ServerRules.IsAllowedToAttack(Caster, npc, true)) { @@ -1186,7 +1186,7 @@ public override void OnEffectPulse(GameSpellEffect effect) { return; } - var ranged = storm.GetDistanceTo(effect.Owner.Position); + var ranged = (int)storm.Coordinate.DistanceTo(effect.Owner.Coordinate); if (ranged > 3000) return; if (s.Name == "Dazzling Array") diff --git a/GameServer/spells/Masterlevel/Perfecter.cs b/GameServer/spells/Masterlevel/Perfecter.cs index 19049430..d3c4fe40 100644 --- a/GameServer/spells/Masterlevel/Perfecter.cs +++ b/GameServer/spells/Masterlevel/Perfecter.cs @@ -50,8 +50,6 @@ public FOHSpellHandler(GameLiving caster, Spell spell, SpellLine line) font.Name = spell.Name; font.Realm = caster.Realm; font.Position = caster.Position; - font.CurrentRegionID = caster.CurrentRegionID; - font.Heading = caster.Heading; font.Owner = (GamePlayer)caster; // Construct the font spell @@ -104,8 +102,6 @@ public FOPSpellHandler(GameLiving caster, Spell spell, SpellLine line) font.Name = spell.Name; font.Realm = caster.Realm; font.Position = caster.Position; - font.CurrentRegionID = caster.CurrentRegionID; - font.Heading = caster.Heading; font.Owner = (GamePlayer)caster; // Construct the font spell @@ -157,8 +153,6 @@ public FORSpellHandler(GameLiving caster, Spell spell, SpellLine line) font.Name = spell.Name; font.Realm = caster.Realm; font.Position = caster.Position; - font.CurrentRegionID = caster.CurrentRegionID; - font.Heading = caster.Heading; font.Owner = (GamePlayer)caster; // Construct the font spell @@ -227,8 +221,6 @@ public FODSpellHandler(GameLiving caster, Spell spell, SpellLine line) font.Name = spell.Name; font.Realm = caster.Realm; font.Position = caster.Position; - font.CurrentRegionID = caster.CurrentRegionID; - font.Heading = caster.Heading; font.Owner = (GamePlayer)caster; // Construct the font spell diff --git a/GameServer/spells/Masterlevel/Sojourner.cs b/GameServer/spells/Masterlevel/Sojourner.cs index 6c78513d..16857975 100644 --- a/GameServer/spells/Masterlevel/Sojourner.cs +++ b/GameServer/spells/Masterlevel/Sojourner.cs @@ -7,8 +7,9 @@ using DOL.AI.Brain; using DOL.GS; using DOL.Events; +using DOL.Geometry; +using DOL.GS.Geometry; using System.Collections.Specialized; -using System.Numerics; using DOL.GS.Profession; namespace DOL.GS.Spells @@ -101,9 +102,8 @@ public AncientTransmuterSpellHandler(GameLiving caster, Spell spell, SpellLine l GamePlayer casterPlayer = caster as GamePlayer; merchant = new GameMerchant(); //Fill the object variables - merchant.Position = casterPlayer.Position + new Vector3(Util.Random(20, 40) - Util.Random(20, 40), Util.Random(20, 40) - Util.Random(20, 40), 0); - merchant.CurrentRegion = casterPlayer.CurrentRegion; - merchant.Heading = (ushort)((casterPlayer.Heading + 2048) % 4096); + merchant.Position = casterPlayer.Position.TurnedAround() + + Vector.Create(Util.Random(-20, 20), Util.Random(-20, 20)); merchant.Level = 1; merchant.Realm = casterPlayer.Realm; merchant.Name = "Ancient Transmuter"; @@ -175,7 +175,7 @@ public class FZSpellHandler : MasterlevelHandling protected RegionTimer m_expireTimer; protected GameNPC m_npc; protected GamePlayer m_target; - protected Vector3 m_loc; + protected Coordinate m_loc; public override void OnDirectEffect(GameLiving target, double effectiveness) { @@ -314,19 +314,18 @@ private void ArriveAtTarget(DOLEvent e, object obj, EventArgs args) if (Caster is GamePlayer) { //Calculate random target - m_loc = GetTargetLoc(); + m_loc = m_npc.Coordinate + Vector.Create(x: Util.Random(-1500, 1500), y: Util.Random(-1500, 1500));; (Caster as GamePlayer).Out.SendCheckLOS((Caster as GamePlayer), m_npc, new CheckLOSResponse(ZephyrCheckLOS)); } } public void ZephyrCheckLOS(GamePlayer player, ushort response, ushort targetOID) { - if ((response & 0x100) == 0x100) - m_npc.PathTo(m_loc.X, m_loc.Y, m_loc.Z, 100); + if ((response & 0x100) == 0x100) m_npc.WalkTo(m_loc, 100); } - public virtual Vector3 GetTargetLoc() + public virtual Coordinate GetTargetLoc() { - return m_npc.Position + new Vector3(Util.Random(-1500, 1500), Util.Random(-1500, 1500), 0); + return m_npc.Coordinate + Vector.Create(Util.Random(-1500, 1500), Util.Random(-1500, 1500), 0); } public override int CalculateSpellResistChance(GameLiving target) diff --git a/GameServer/spells/Masterlevel/Spymaster.cs b/GameServer/spells/Masterlevel/Spymaster.cs index 7adec030..f881f4f7 100644 --- a/GameServer/spells/Masterlevel/Spymaster.cs +++ b/GameServer/spells/Masterlevel/Spymaster.cs @@ -96,8 +96,7 @@ public DecoySpellHandler(GameLiving caster, Spell spell, SpellLine line) decoy = new GameDecoy(); //Fill the object variables decoy.CurrentRegion = caster.CurrentRegion; - decoy.Heading = (ushort)((caster.Heading + 2048) % 4096); - decoy.Level = 50; + decoy.Position = caster.Position.TurnedAround(); decoy.Realm = caster.Realm; decoy.Position = caster.Position; string TemplateId = ""; @@ -177,8 +176,6 @@ public TangleSnareSpellHandler(GameLiving caster, Spell spell, SpellLine line) mine.Name = spell.Name; mine.Realm = caster.Realm; mine.Position = caster.Position; - mine.CurrentRegionID = caster.CurrentRegionID; - mine.Heading = caster.Heading; mine.Owner = (GamePlayer)caster; // Construct the mine spell @@ -228,8 +225,6 @@ public PoisonSpikeSpellHandler(GameLiving caster, Spell spell, SpellLine line) mine.Name = spell.Name; mine.Realm = caster.Realm; mine.Position = caster.Position; - mine.CurrentRegionID = caster.CurrentRegionID; - mine.Heading = caster.Heading; mine.Owner = (GamePlayer)caster; // Construct the mine spell @@ -372,8 +367,6 @@ public SiegeWreckerSpellHandler(GameLiving caster, Spell spell, SpellLine line) mine.Realm = caster.Realm; mine.Position = caster.Position; mine.MaxSpeedBase = 0; - mine.CurrentRegionID = caster.CurrentRegionID; - mine.Heading = caster.Heading; mine.Owner = (GamePlayer)caster; // Construct the mine spell diff --git a/GameServer/spells/Masterlevel/Stormlord.cs b/GameServer/spells/Masterlevel/Stormlord.cs index 2adc2472..2cfeac27 100644 --- a/GameServer/spells/Masterlevel/Stormlord.cs +++ b/GameServer/spells/Masterlevel/Stormlord.cs @@ -23,9 +23,9 @@ using DOL.GS.Effects; using DOL.Database; using DOL.Events; +using DOL.GS.Geometry; using System.Collections; using System.Collections.Generic; -using System.Numerics; namespace DOL.GS.Spells { @@ -43,8 +43,6 @@ public DazzlingArraySpellHandler(GameLiving caster, Spell spell, SpellLine line) storm = new GameStorm(); storm.Realm = caster.Realm; storm.Position = caster.Position; - storm.CurrentRegionID = caster.CurrentRegionID; - storm.Heading = caster.Heading; storm.Owner = (GamePlayer)caster; storm.Movable = true; @@ -155,8 +153,8 @@ public override void OnDirectEffect(GameLiving target, double effectiveness) GameNPC targetNPC = targetStorm as GameNPC; int range = Util.Random(0, 750); double angle = Util.RandomDouble() * 2 * Math.PI; - var rand = new Vector3(range * (float)Math.Cos(angle), range * (float)Math.Sin(angle), 0); - targetNPC.PathTo(targetNPC.Position + rand, targetNPC.MaxSpeed); + var offset = Vector.Create(x: (int)(range * Math.Cos(angle)), y: (int)(range * Math.Sin(angle)) ); + targetNPC.WalkTo(targetNPC.Coordinate + offset, targetNPC.MaxSpeed); } } } @@ -181,8 +179,6 @@ public EnervatingGasSpellHandler(GameLiving caster, Spell spell, SpellLine line) storm = new GameStorm(); storm.Realm = caster.Realm; storm.Position = caster.Position; - storm.CurrentRegionID = caster.CurrentRegionID; - storm.Heading = caster.Heading; storm.Owner = (GamePlayer)caster; storm.Movable = true; @@ -266,8 +262,6 @@ public InebriatingFumesSpellHandler(GameLiving caster, Spell spell, SpellLine li storm = new GameStorm(); storm.Realm = caster.Realm; storm.Position = caster.Position; - storm.CurrentRegionID = caster.CurrentRegionID; - storm.Heading = caster.Heading; storm.Owner = (GamePlayer)caster; storm.Movable = true; @@ -347,8 +341,6 @@ public MentalSiphonSpellHandler(GameLiving caster, Spell spell, SpellLine line) storm = new GameStorm(); storm.Realm = caster.Realm; storm.Position = caster.Position; - storm.CurrentRegionID = caster.CurrentRegionID; - storm.Heading = caster.Heading; storm.Owner = (GamePlayer)caster; storm.Movable = true; @@ -505,8 +497,6 @@ public ChokingVaporsSpellHandler(GameLiving caster, Spell spell, SpellLine line) storm = new GameStorm(); storm.Realm = caster.Realm; storm.Position = caster.Position; - storm.CurrentRegionID = caster.CurrentRegionID; - storm.Heading = caster.Heading; storm.Owner = (GamePlayer)caster; storm.Movable = true; @@ -586,8 +576,6 @@ public SenseDullingCloudSpellHandler(GameLiving caster, Spell spell, SpellLine l storm = new GameStorm(); storm.Realm = caster.Realm; storm.Position = caster.Position; - storm.CurrentRegionID = caster.CurrentRegionID; - storm.Heading = caster.Heading; storm.Owner = (GamePlayer)caster; storm.Movable = true; @@ -666,8 +654,6 @@ public EnergyTempestSpellHandler(GameLiving caster, Spell spell, SpellLine line) storm = new GameStorm(); storm.Realm = caster.Realm; storm.Position = caster.Position; - storm.CurrentRegionID = caster.CurrentRegionID; - storm.Heading = caster.Heading; storm.Owner = (GamePlayer)caster; storm.Movable = true; diff --git a/GameServer/spells/ResurrectSpellHandler.cs b/GameServer/spells/ResurrectSpellHandler.cs index 39d60a31..f4684ee4 100644 --- a/GameServer/spells/ResurrectSpellHandler.cs +++ b/GameServer/spells/ResurrectSpellHandler.cs @@ -170,7 +170,7 @@ protected virtual void ResurrectLiving(GameLiving living) else living.Endurance = 0; - living.MoveTo(m_caster.CurrentRegionID, m_caster.Position, m_caster.Heading); + living.MoveTo(m_caster.Position); GameTimer resurrectExpiredTimer = null; lock (m_resTimersByLiving.SyncRoot) diff --git a/GameServer/spells/SpellHandler.cs b/GameServer/spells/SpellHandler.cs index 9bd124fe..f45288b0 100644 --- a/GameServer/spells/SpellHandler.cs +++ b/GameServer/spells/SpellHandler.cs @@ -773,7 +773,7 @@ public virtual bool CheckBeginCast(GameLiving selectedTarget, bool quiet) } if (targetType == "area") { - if (!m_caster.IsWithinRadius(m_caster.GroundTarget.Value, CalculateSpellRange())) + if (!m_caster.IsWithinRadius(m_caster.GroundTargetPosition, CalculateSpellRange())) { if (!quiet) MessageToCaster("Your area target is out of range. Select a closer target.", eChatType.CT_SpellResisted); return false; @@ -1045,7 +1045,7 @@ public virtual bool CheckEndCast(GameLiving target) if (m_spell.Target.ToLower() == "area") { - if (!m_caster.IsWithinRadius(m_caster.GroundTarget.Value, CalculateSpellRange())) + if (!m_caster.IsWithinRadius(m_caster.GroundTargetPosition, CalculateSpellRange())) { MessageToCaster("Your area target is out of range. Select a closer target.", eChatType.CT_SpellResisted); return false; @@ -1221,7 +1221,7 @@ public virtual bool CheckDuringCast(GameLiving target, bool quiet) if (m_spell.Target.ToLower() == "area") { - if (!m_caster.IsWithinRadius(m_caster.GroundTarget.Value, CalculateSpellRange())) + if (!m_caster.IsWithinRadius(m_caster.GroundTargetPosition, CalculateSpellRange())) { if (!quiet) MessageToCaster("Your area target is out of range. Select a closer target.", eChatType.CT_SpellResisted); return false; @@ -1432,7 +1432,7 @@ public virtual bool CheckAfterCast(GameLiving target, bool quiet) if (m_spell.Target.ToLower() == "area") { - if (!m_caster.IsWithinRadius(m_caster.GroundTarget.Value, CalculateSpellRange())) + if (!m_caster.IsWithinRadius(m_caster.GroundTargetPosition, CalculateSpellRange())) { if (!quiet) MessageToCaster("Your area target is out of range. Select a closer target.", eChatType.CT_SpellResisted); return false; @@ -2105,7 +2105,7 @@ public virtual IList SelectTargets(GameObject castTarget, bool force else if (modifiedRadius > 0) { - foreach (GamePlayer player in WorldMgr.GetPlayersCloseToSpot(Caster.CurrentRegionID, Caster.GroundTarget.Value, modifiedRadius)) + foreach (GamePlayer player in WorldMgr.GetPlayersCloseToSpot(Caster.GroundTargetPosition, modifiedRadius)) { if (GameServer.ServerRules.IsAllowedToAttack(Caster, player, true) || force) { @@ -2123,7 +2123,7 @@ public virtual IList SelectTargets(GameObject castTarget, bool force else list.Add(player); } } - foreach (GameNPC npc in WorldMgr.GetNPCsCloseToSpot(Caster.CurrentRegionID, Caster.GroundTarget.Value, modifiedRadius)) + foreach (GameNPC npc in WorldMgr.GetNPCsCloseToSpot(Caster.GroundTargetPosition, modifiedRadius)) { if (npc is GameStorm) list.Add(npc); @@ -2597,20 +2597,20 @@ public virtual bool StartSpell(GameLiving target, bool force = false) } else if (Spell.Target.ToLower() == "area") { - var dist = Vector3.Distance(t.Position, Caster.GroundTarget.Value); + int dist = (int)t.Coordinate.DistanceTo(Caster.GroundTargetPosition); if (dist >= 0) ApplyEffectOnTarget(t, (effectiveness - CalculateAreaVariance(t, dist, Spell.Radius))); } else if (Spell.Target.ToLower() == "cone") { - var dist = Vector3.Distance(t.Position, Caster.Position); + var dist = (int)t.Coordinate.DistanceTo(Caster.Position); //Cone spells use the range for their variance! if (dist >= 0) ApplyEffectOnTarget(t, (effectiveness - CalculateAreaVariance(t, dist, Spell.Range))); } else { - var dist = Vector3.Distance(t.Position, target.Position); + var dist = (int)t.Coordinate.DistanceTo(target.Position); if (dist >= 0) ApplyEffectOnTarget(t, (effectiveness - CalculateAreaVariance(t, dist, Spell.Radius))); } diff --git a/GameServer/spells/SummonIllusionBlade.cs b/GameServer/spells/SummonIllusionBlade.cs index ef4533a4..a8c3d067 100644 --- a/GameServer/spells/SummonIllusionBlade.cs +++ b/GameServer/spells/SummonIllusionBlade.cs @@ -47,15 +47,7 @@ public override void ApplyEffectOnTarget(GameLiving target, double effectiveness IControlledBrain brain = GetPetBrain(Caster); m_pet = GetGamePet(template); m_pet.SetOwnBrain(brain as AI.ABrain); - Vector3 pos; - ushort heading; - Region region; - - GetPetLocation(out pos, out heading, out region); - - m_pet.Position = pos; - m_pet.Heading = heading; - m_pet.CurrentRegion = region; + m_pet.Position = GetSummonPosition(); // m_pet.CurrentSpeed = 0; m_pet.Realm = Caster.Realm; m_pet.Race = 0; diff --git a/GameServer/spells/SummonSpellHandler.cs b/GameServer/spells/SummonSpellHandler.cs index a6d13757..36af8d40 100644 --- a/GameServer/spells/SummonSpellHandler.cs +++ b/GameServer/spells/SummonSpellHandler.cs @@ -20,11 +20,11 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Numerics; using System.Reflection; using DOL.AI.Brain; using DOL.Events; using DOL.GS.Effects; +using DOL.GS.Geometry; using DOL.GS.PacketHandler; using DOL.Language; @@ -87,13 +87,19 @@ public override void FinishSpellCast(GameLiving target) #region ApplyEffectOnTarget Gets - protected virtual void GetPetLocation(out Vector3 position, out ushort heading, out Region region) + [Obsolete("Use GetSummonPosition() instead!")] + protected virtual void GetPetLocation(out int x, out int y, out int z, out ushort heading, out Region region) { - Vector2 point = Caster.GetPointFromHeading(Caster.Heading, 64); - position = new Vector3(point, Caster.Position.Z); - heading = (ushort)((Caster.Heading + 2048) % 4096); - region = Caster.CurrentRegion; + var position = GetSummonPosition(); + x = position.X; + y = position.Y; + z = position.Z; + heading = position.Orientation.InHeading; + region = WorldMgr.GetRegion(position.RegionID); } + + protected virtual Position GetSummonPosition() + => Caster.Position.TurnedAround() + Vector.Create(Caster.Orientation, length: 64); protected virtual GamePet GetGamePet(INpcTemplate template) { @@ -153,16 +159,7 @@ public override void ApplyEffectOnTarget(GameLiving target, double effectiveness m_pet.SummonSpellDamage = Spell.Damage; m_pet.SummonSpellValue = Spell.Value; - - Vector3 pos; - ushort heading; - Region region; - - GetPetLocation(out pos, out heading, out region); - - m_pet.Position = pos; - m_pet.Heading = heading; - m_pet.CurrentRegion = region; + m_pet.Position = GetSummonPosition(); m_pet.Realm = Caster.Realm; diff --git a/GameServer/spells/Teleport/GatewayPersonalBind.cs b/GameServer/spells/Teleport/GatewayPersonalBind.cs index 4ca778ae..bef6ad6e 100644 --- a/GameServer/spells/Teleport/GatewayPersonalBind.cs +++ b/GameServer/spells/Teleport/GatewayPersonalBind.cs @@ -106,7 +106,7 @@ public override void ApplyEffectOnTarget(GameLiving target, double effectiveness UniPortalEffect effect = new UniPortalEffect(this, 1000); effect.Start(player); - player.MoveTo((ushort)player.BindRegion, player.BindXpos, player.BindYpos, player.BindZpos, (ushort)player.BindHeading); + player.MoveTo(player.BindPosition); } diff --git a/GameServer/spells/Theurgist/SummonTheurgistPet.cs b/GameServer/spells/Theurgist/SummonTheurgistPet.cs index 9a0579c4..c99bece6 100644 --- a/GameServer/spells/Theurgist/SummonTheurgistPet.cs +++ b/GameServer/spells/Theurgist/SummonTheurgistPet.cs @@ -19,7 +19,7 @@ using DOL.GS.PacketHandler; using DOL.AI.Brain; using DOL.GS.Effects; -using System.Numerics; +using DOL.GS.Geometry; namespace DOL.GS.Spells { @@ -75,10 +75,7 @@ protected override IControlledBrain GetPetBrain(GameLiving owner) protected override void SetBrainToOwner(IControlledBrain brain) { } - protected override void GetPetLocation(out Vector3 pos, out ushort heading, out Region region) - { - base.GetPetLocation(out pos, out heading, out region); - heading = Caster.Heading; - } + protected override Position GetSummonPosition() + => Caster.Position + Vector.Create(Caster.Orientation, length: 64); } } diff --git a/GameServer/spells/negative/FearBrain.cs b/GameServer/spells/negative/FearBrain.cs index 731d28b9..b4bc60fc 100644 --- a/GameServer/spells/negative/FearBrain.cs +++ b/GameServer/spells/negative/FearBrain.cs @@ -17,8 +17,8 @@ * */ using System; -using System.Numerics; using DOL.GS; +using DOL.GS.Geometry; namespace DOL.AI.Brain { @@ -53,13 +53,12 @@ public override void Think() ///The target to flee. protected virtual void CalculateFleeTarget(GameLiving target) { - ushort TargetAngle = (ushort)((Body.GetHeading(target) + 2048) % 4096); + var targetAngle = Body.Coordinate.GetOrientationTo(target.Coordinate) + Angle.Degrees(180); - var fleePoint = Body.GetPointFromHeading(TargetAngle, 300); - var point = PathingMgr.Instance.GetClosestPoint(Body.CurrentZone, new Vector3(fleePoint, Body.Position.Z), 128, 128, 256); Body.StopFollowing(); Body.StopAttack(); - Body.PathTo(point.HasValue ? point.Value : new Vector3(fleePoint, Body.Position.Z), Body.MaxSpeed); + var destination = Body.Position + Vector.Create(targetAngle, length: 300); + Body.PathTo(destination.Coordinate, Body.MaxSpeed); } /// diff --git a/GameServer/styles/StyleProcessor.cs b/GameServer/styles/StyleProcessor.cs index 02b42bd5..26b99c35 100644 --- a/GameServer/styles/StyleProcessor.cs +++ b/GameServer/styles/StyleProcessor.cs @@ -143,7 +143,7 @@ public static bool CanUseStyle(GameLiving living, Style style, InventoryItem wea return false; // get players angle on target - float angle = GameMath.GetAngle(target, living); + var angle = target.GetAngleTo(living.Coordinate); //player.Out.SendDebugMessage("Positional check: "+style.OpeningRequirementValue+" angle "+angle+" target heading="+target.Heading); switch ((Style.eOpeningPosition)style.OpeningRequirementValue) @@ -151,17 +151,17 @@ public static bool CanUseStyle(GameLiving living, Style style, InventoryItem wea //Back Styles //60 degree since 1.62 patch case Style.eOpeningPosition.Back: - if (!(angle >= 150 && angle < 210)) return false; + if (angle.InDegrees is < 150 or >= 210) return false; break; // Side Styles //105 degree since 1.62 patch case Style.eOpeningPosition.Side: - if (!(angle >= 45 && angle < 150) && !(angle >= 210 && angle < 315)) return false; + if (angle.InDegrees is (< 45 or >= 150) and (< 210 or >= 315)) return false; break; // Front Styles // 90 degree case Style.eOpeningPosition.Front: - if (!(angle >= 315 || angle < 45)) return false; + if (angle.InDegrees is < 315 and >= 45) return false; break; } //DOLConsole.WriteLine("Positional check success: "+style.OpeningRequirementValue); diff --git a/GameServer/world/AbstractArea.cs b/GameServer/world/AbstractArea.cs index 9d24b00c..25ca22e1 100644 --- a/GameServer/world/AbstractArea.cs +++ b/GameServer/world/AbstractArea.cs @@ -22,7 +22,6 @@ using DOL.Events; using DOL.Language; using DOL.GS.PacketHandler; -using System.Numerics; using DOL.GameEvents; using DOL.GS.Geometry; using System.Linq; @@ -234,18 +233,13 @@ public void RegisterPlayerLeave(DOLEventHandler callback) /// public abstract bool IsContaining(Coordinate spot, bool checkZ); - public bool IsContaining(Coordinate spot) - { - return IsContaining(spot, true); - } - public bool IsContaining(int x, int y, int z, bool checkZ) - { - return IsContaining(Coordinate.Create(x, y, z), checkZ); - } - public bool IsContaining(int x, int y, int z) - { - return IsContaining(Coordinate.Create(x, y, z), true); - } + public bool IsContaining(Coordinate spot) => IsContaining(spot, true); + + [Obsolete("Use .IsContaining(Coordinate[,bool]) instead!")] + public bool IsContaining(int x, int y, int z, bool checkZ) => IsContaining(Coordinate.Create(x, y, z), checkZ); + + [Obsolete("Use .IsContaining(Coordinate[,bool]) instead!")] + public bool IsContaining(int x, int y, int z) => IsContaining(Coordinate.Create(x, y, z), true); /// /// Get the distance to the closest edge of this area from a point diff --git a/GameServer/world/Instance/BaseInstance.cs b/GameServer/world/Instance/BaseInstance.cs index 1d08808a..48780f59 100644 --- a/GameServer/world/Instance/BaseInstance.cs +++ b/GameServer/world/Instance/BaseInstance.cs @@ -30,7 +30,7 @@ using DOL.GS; using DOL.Database; -using System.Numerics; +using DOL.GS.Geometry; namespace DOL.GS { @@ -420,7 +420,7 @@ protected override void OnTick() /// /// /// - public override IList GetAreasOfZone(Zone zone, Vector3 p, bool checkZ) + public override IList GetAreasOfZone(Zone zone, Coordinate loc, bool checkZ) { Zone checkZone = zone; var areas = new List(); @@ -447,7 +447,7 @@ public override IList GetAreasOfZone(Zone zone, Vector3 p, bool checkZ) for (int i = 0; i < m_ZoneAreasCount[zoneIndex]; i++) { IArea area = (IArea)Areas[m_ZoneAreas[zoneIndex][i]]; - if (area.IsContaining(p, checkZ)) + if (area.IsContaining(loc, checkZ)) { areas.Add(area); } @@ -470,7 +470,7 @@ public override IList GetAreasOfZone(Zone zone, Vector3 p, bool checkZ) /// /// /// - public override IList GetAreasOfZone(Zone zone, int x, int y, int z) + public override IList GetAreasOfZone(Zone zone, Coordinate loc) { Zone checkZone = zone; var areas = new List(); @@ -497,7 +497,7 @@ public override IList GetAreasOfZone(Zone zone, int x, int y, int z) for (int i = 0; i < m_ZoneAreasCount[zoneIndex]; i++) { IArea area = (IArea)Areas[m_ZoneAreas[zoneIndex][i]]; - if (area.IsContaining(x, y, z)) + if (area.IsContaining(loc)) areas.Add(area); } } diff --git a/GameServer/world/Instance/Instance.cs b/GameServer/world/Instance/Instance.cs index a9806834..d575e6cc 100644 --- a/GameServer/world/Instance/Instance.cs +++ b/GameServer/world/Instance/Instance.cs @@ -27,7 +27,7 @@ using DOL.Database; using DOL.GS.Utils; using log4net; -using System.Numerics; +using DOL.GS.Geometry; namespace DOL.GS { @@ -54,13 +54,13 @@ public Instance(ushort ID, GameTimer.TimeManager time, RegionData data) : base(I #region Entrance - protected GameLocation m_entranceLocation = null; + [Obsolete("Use .InstanceEntranceName or .EntrancePosition instead!")] + public GameLocation InstanceEntranceLocation => new GameLocation(EntrancePosition); - /// - /// Returns the entrance location into this instance. - /// - public GameLocation InstanceEntranceLocation - { get { return m_entranceLocation; } } + [Obsolete("This is going to be removed.")] + public string InstanceEntranceName { get; set; } = null; + + public Position EntrancePosition { get; set; } = Position.Nowhere; #endregion @@ -95,7 +95,7 @@ public virtual void LoadFromDatabase(string instanceName) case "entrance": { //create the entrance, then move to the next. - m_entranceLocation = new GameLocation(instanceName + "entranceRegion" + ID, ID, entry.X, entry.Y, entry.Z, entry.Heading); + EntrancePosition = Position.Create(regionID: ID, entry.X, entry.Y, entry.Z, entry.Heading); //move to the next entry, nothing more to do here... continue; } @@ -119,7 +119,7 @@ public virtual void LoadFromDatabase(string instanceName) //We now have an object that isnt null. Lets place it at the location, in this region. - obj.Position = new Vector3(entry.X, entry.Y, entry.Z); + obj.Position = Position.Create(regionID: ID, entry.X, entry.Y, entry.Z, entry.Heading); obj.Heading = entry.Heading; obj.CurrentRegionID = ID; diff --git a/GameServer/world/Instance/RegionInstance.cs b/GameServer/world/Instance/RegionInstance.cs index e52f7b2d..63b34433 100644 --- a/GameServer/world/Instance/RegionInstance.cs +++ b/GameServer/world/Instance/RegionInstance.cs @@ -46,11 +46,6 @@ public class RegionInstance : BaseInstance /// private List m_players_in; - /// - /// Entrance location of Instance, needed to force exit players. - /// - protected GameLocation m_sourceentrance; - /// /// List Containing players in instance /// @@ -59,15 +54,6 @@ protected List PlayersInside get { return m_players_in; } } - /// - /// Entrance location of Instance, needed to force exit players. - /// - public GameLocation SourceEntrance - { - get { return m_sourceentrance; } - set { m_sourceentrance = value; } - } - /// /// On Player Enter override to add him to container /// diff --git a/GameServer/world/Region.cs b/GameServer/world/Region.cs index 754e6d6a..2503b295 100644 --- a/GameServer/world/Region.cs +++ b/GameServer/world/Region.cs @@ -635,7 +635,7 @@ public virtual GameKeepComponent CreateGameKeepComponent() public virtual void CreateCombatZone(Guild owningGuild, Position position) { - Area.CombatZone zone = new(owningGuild, position); + Area.CombatZone zone = new(owningGuild, position.Coordinate); AddArea(zone); CombatZoneBanner banner = CombatZoneBanner.Create(owningGuild, zone); @@ -1512,7 +1512,7 @@ public virtual IList GetAreasInRadius(Coordinate center, float radius, bo var areas = new List(); foreach (Zone zone in m_zones) { - if (zone.XOffset <= p.X + radius && (zone.XOffset + zone.Width) > p.X - radius && zone.YOffset <= p.Y + radius && (zone.YOffset + zone.Height) > p.Y - radius) + if (zone.Offset.X <= center.X + radius && (zone.Offset.X + zone.Width) > center.X - radius && zone.Offset.Y <= center.Y + radius && (zone.Offset.Y + zone.Height) > center.Y - radius) { float radiusSquared = radius * radius; @@ -1556,7 +1556,7 @@ public virtual IArea FindAnyAreaInRadius(Coordinate center, float radius, bool c int zoneIndex = 0; foreach (Zone zone in m_zones) { - if (zone.XOffset <= p.X + radius && (zone.XOffset + zone.Width) > p.X - radius && zone.YOffset <= p.Y + radius && (zone.YOffset + zone.Height) > p.Y - radius) + if (zone.Offset.X <= center.X + radius && (zone.Offset.X + zone.Width) > center.X - radius && zone.Offset.Y <= center.Y + radius && (zone.Offset.Y + zone.Height) > center.Y - radius) { float radiusSquared = radius * radius; diff --git a/GameServer/world/TeleportArea.cs b/GameServer/world/TeleportArea.cs index b08696d2..f8ef885e 100644 --- a/GameServer/world/TeleportArea.cs +++ b/GameServer/world/TeleportArea.cs @@ -21,6 +21,7 @@ using DOL.GS; using DOL.Database; +using DOL.GS.Geometry; using DOL.GS.PacketHandler; namespace DOL.GS @@ -52,9 +53,8 @@ protected void OnTeleport(GamePlayer player, Teleport destination) if (player.InCombat == false && GameRelic.IsPlayerCarryingRelic(player) == false) { player.LeaveHouse(); - GameLocation currentLocation = new GameLocation("TeleportStart", player.CurrentRegionID, player.Position, player.Heading); - player.MoveTo((ushort)destination.RegionID, destination.X, destination.Y, destination.Z, (ushort)destination.Heading); - GameServer.ServerRules.OnPlayerTeleport(player, currentLocation, destination); + player.MoveTo(destination.GetPosition()); + GameServer.ServerRules.OnPlayerTeleport(player, destination); } } @@ -66,5 +66,7 @@ protected void OnTeleport(GamePlayer player, Teleport destination) /// public class TeleportPillarArea : TeleportArea { + public override bool IsContaining(Coordinate spot, bool ignoreZ) + => base.IsContaining(spot, checkZ: false); } } diff --git a/GameServer/world/WorldMgr.cs b/GameServer/world/WorldMgr.cs index 8348c706..3aaa28f2 100644 --- a/GameServer/world/WorldMgr.cs +++ b/GameServer/world/WorldMgr.cs @@ -30,10 +30,10 @@ using DOL.GS.PacketHandler; using DOL.GS.Utils; using DOL.Config; +using DOL.GS.Geometry; using DOL.GS.Housing; using log4net; -using System.Numerics; namespace DOL.GS { @@ -1811,123 +1811,50 @@ public static GameObject GetObjectTypeByIDFromRegion(ushort regionID, ushort oID return obj; } - /// - /// Returns an IEnumerator of GamePlayers that are close to a certain - /// spot in the region - /// - /// Region to search - /// X inside region - /// Y inside region - /// Z inside region - /// Wether or not to return the objects with distance - /// Radius to sarch for GameClients - /// IEnumerator that can be used to go through all players - public static IEnumerable GetPlayersCloseToSpot(ushort regionid, float x, float y, float z, ushort radiusToCheck, bool withDistance) - { - Region reg = GetRegion(regionid); - if (reg == null) - return new Region.EmptyEnumerator(); - return reg.GetPlayersInRadius(x, y, z, radiusToCheck, withDistance, false); - } - - /// - /// Returns an IEnumerator of GamePlayers that are close to a certain - /// spot in the region - /// - /// the game location to search from - /// Radius to sarch for GameClients - /// IEnumerator that can be used to go through all players - public static IEnumerable GetPlayersCloseToSpot(IGameLocation location, ushort radiusToCheck) - { - var p = location.Position; - return GetPlayersCloseToSpot(location.RegionID, p.X, p.Y, p.Z, radiusToCheck, false); - } + [Obsolete("Use GetPlayersCloseToSpot(Position,ushort) instead!")] + public static IEnumerable GetPlayersCloseToSpot(ushort regionid, int x, int y, int z, ushort radiusToCheck, bool withDistance = false) + => GetPlayersCloseToSpot(Position.Create(regionid, x, y, z), radiusToCheck); + + [Obsolete("Use GetPlayersCloseToSpot(Position,ushort) instead!")] + public static IEnumerable GetPlayersCloseToSpot(IGameLocation location, ushort radiusToCheck, bool withDistance = false) + => GetPlayersCloseToSpot(location.Position, radiusToCheck); - /// - /// Returns an IEnumerator of GamePlayers that are close to a certain - /// spot in the region - /// - /// Region to search - /// the 3D point to search from - /// Radius to sarch for GameClients - /// IEnumerator that can be used to go through all players - public static IEnumerable GetPlayersCloseToSpot(ushort regionid, Vector3 point, ushort radiusToCheck) + public static IEnumerable GetPlayersCloseToSpot(Position position, ushort radiusToCheck, bool withDistance = false) { - return GetPlayersCloseToSpot(regionid, point.X, point.Y, point.Z, radiusToCheck, false); - } - - /// - /// Returns an IEnumerator of GamePlayers that are close to a certain - /// spot in the region - /// - /// Region to search - /// X inside region - /// Y inside region - /// Z inside region - /// Radius to sarch for GameClients - /// IEnumerator that can be used to go through all players - public static IEnumerable GetPlayersCloseToSpot(ushort regionid, float x, float y, float z, ushort radiusToCheck) - { - return GetPlayersCloseToSpot(regionid, x, y, z, radiusToCheck, false); - } - - /// - /// Returns an IEnumerator of GameNPCs that are close to a certain - /// spot in the region - /// - /// Region to search - /// X inside region - /// Y inside region - /// Z inside region - /// Radius to sarch for GameNPCs - /// Wether or not to return the objects with distance - /// IEnumerator that can be used to go through all NPCs - public static IEnumerable GetNPCsCloseToSpot(ushort regionid, float x, float y, float z, ushort radiusToCheck, bool withDistance) - { - Region reg = GetRegion(regionid); + Region reg = GetRegion(position.RegionID); if (reg == null) return new Region.EmptyEnumerator(); - return reg.GetNPCsInRadius(x, y, z, radiusToCheck, withDistance, false); + return reg.GetPlayersInRadius(position.Coordinate, radiusToCheck, false, withDistance); } - /// - /// Returns an IEnumerator of GameNPCs that are close to a certain - /// spot in the region - /// - /// Region to search - /// X inside region - /// Y inside region - /// Z inside region - /// Radius to sarch for GameNPCs - /// IEnumerator that can be used to go through all NPCs - public static IEnumerable GetNPCsCloseToSpot(ushort regionid, float x, float y, float z, ushort radiusToCheck) + [Obsolete("Use GetNPCsCloseToSpot(Position,ushort) instead!")] + public static IEnumerable GetNPCsCloseToSpot(ushort regionid, int x, int y, int z, ushort radiusToCheck, bool withDistance = false) + => GetNPCsCloseToSpot(Position.Create(regionid, x, y, z), radiusToCheck); + + [Obsolete("Use GetNPCsCloseToSpot(Position,ushort) instead!")] + public static IEnumerable GetNPCsCloseToSpot(IGameLocation location, ushort radiusToCheck, bool withDistance = false) + => GetNPCsCloseToSpot(location.Position, radiusToCheck); + + public static IEnumerable GetNPCsCloseToSpot(Position position, ushort radiusToCheck, bool withDistance = false) { - return GetNPCsCloseToSpot(regionid, x, y, z, radiusToCheck, false); + Region reg = GetRegion(position.RegionID); + if (reg == null) return new Region.EmptyEnumerator(); + return reg.GetNPCsInRadius(position.Coordinate, radiusToCheck, false, withDistance); } - public static IEnumerable GetNPCsCloseToSpot(ushort regionid, Vector3 pos, ushort radiusToCheck, bool withDistance) - => GetNPCsCloseToSpot(regionid, pos.X, pos.Y, pos.Z, radiusToCheck, withDistance); - public static IEnumerable GetNPCsCloseToSpot(ushort regionid, Vector3 pos, ushort radiusToCheck) - => GetNPCsCloseToSpot(regionid, pos.X, pos.Y, pos.Z, radiusToCheck, false); + [Obsolete("Use GetItemsCloseToSpot(Position,ushort) instead!")] + public static IEnumerable GetItemsCloseToSpot(ushort regionid, int x, int y, int z, ushort radiusToCheck, bool withDistance = false) + => GetNPCsCloseToSpot(Position.Create(regionid, x, y, z), radiusToCheck); + + [Obsolete("Use GetItemsCloseToSpot(Position,ushort) instead!")] + public static IEnumerable GetItemsCloseToSpot(IGameLocation location, ushort radiusToCheck, bool withDistance = false) + => GetItemsCloseToSpot(location.Position, radiusToCheck); - /// - /// Returns an IEnumerator of GameItems that are close to a certain - /// spot in the region - /// - /// Region to search - /// X inside region - /// Y inside region - /// Z inside region - /// Radius to sarch for GameItems - /// Wether or not to return the objects with distance - /// IEnumerator that can be used to go through all items - public static IEnumerable GetItemsCloseToSpot(ushort regionid, float x, float y, float z, ushort radiusToCheck, bool withDistance) + public static IEnumerable GetItemsCloseToSpot(Position position, ushort radiusToCheck, bool withDistance = false) { - Region reg = GetRegion(regionid); - if (reg == null) - return new Region.EmptyEnumerator(); - - return reg.GetItemsInRadius(x, y, z, radiusToCheck, withDistance); + Region reg = GetRegion(position.RegionID); + if (reg == null) return new Region.EmptyEnumerator(); + return reg.GetItemsInRadius(position.Coordinate, radiusToCheck, withDistance); } /// diff --git a/GameServer/world/WorldUpdateThread.cs b/GameServer/world/WorldUpdateThread.cs index b08ca27b..540442be 100644 --- a/GameServer/world/WorldUpdateThread.cs +++ b/GameServer/world/WorldUpdateThread.cs @@ -372,8 +372,10 @@ public static void UpdatePlayerHousing(GamePlayer player, uint nowTicks) // Get All House in Region IDictionary housesDict = HouseMgr.GetHouses(player.CurrentRegionID); - // Build Vincinity List - var houses = housesDict.Values.Where(h => h != null && player.IsWithinRadius(h.Position, HousingConstants.HouseViewingDistance)).ToArray(); + // Build Vicinity List + var houses = housesDict.Values + .Where(h => h != null && player.Coordinate.DistanceTo(h.Position) <= HousingConstants.HouseViewingDistance) + .ToArray(); try { diff --git a/GameServer/world/ZonePointEffects.cs b/GameServer/world/ZonePointEffects.cs index 250f0f63..de32ce14 100644 --- a/GameServer/world/ZonePointEffects.cs +++ b/GameServer/world/ZonePointEffects.cs @@ -22,6 +22,7 @@ using DOL.Events; using DOL.Database; +using DOL.GS.Geometry; using System.Numerics; namespace DOL.GS.GameEvents @@ -50,7 +51,7 @@ public static void OnScriptsCompiled(DOLEvent e, object sender, EventArgs args) // processing all the ZP IList zonePoints = GameServer.Database.SelectAllObjects(); - foreach (ZonePoint z in zonePoints) + foreach (var z in zonePoints) { if (z.SourceRegion == 0) continue; @@ -64,8 +65,7 @@ public static void OnScriptsCompiled(DOLEvent e, object sender, EventArgs args) GameNPC npc = new GameNPC(zp); - npc.CurrentRegionID = z.SourceRegion; - npc.Position = new Vector3(z.SourceX, z.SourceY, z.SourceZ); + npc.Position = z.GetSourcePosition().With(npc.Orientation); npc.Name = r.Description; npc.GuildName = "ZonePoint (Open)"; if (r.IsDisabled) npc.GuildName = "ZonePoint (Closed)"; diff --git a/Tests/IntegrationTests/GameServer/gameutils/RegionTest.cs b/Tests/IntegrationTests/GameServer/gameutils/RegionTest.cs index de3ffb77..5dcfe46b 100644 --- a/Tests/IntegrationTests/GameServer/gameutils/RegionTest.cs +++ b/Tests/IntegrationTests/GameServer/gameutils/RegionTest.cs @@ -17,104 +17,103 @@ * */ using System; -using System.Numerics; using DOL.Events; using DOL.GS; +using DOL.GS.Geometry; using NUnit.Framework; namespace DOL.Integration.Server { - [TestFixture] - public class RegionTest : ServerTests - { - public static bool notified = false; - - public RegionTest() - { - } - - [Test, Explicit] - public void AddObject() - { - Region region = WorldMgr.GetRegion(1); - GameObject obj = new GameNPC(); - obj.Name = "TestObject"; - obj.Position = new Vector3(400000, 200000, 2000); - obj.CurrentRegion = region; - - obj.AddToWorld(); - - if (obj.ObjectID < 0) - Assert.Fail("Failed to add object to Region. ObjectId < 0"); - - Assert.AreEqual(region.GetObject((ushort)obj.ObjectID), obj); - } - - - [Test, Explicit] - public void AddArea() - { - Region region = WorldMgr.GetRegion(1); - IArea insertArea = region.AddArea(new Area.Circle(null, 1000, 1000, 0, 500)); - - Assert.IsNotNull(insertArea); - - var areas = region.GetAreasOfSpot(501, 1000, 0); - Assert.IsTrue(areas.Count > 0); - - bool found = false; - foreach (IArea ar in areas) - { - if (ar == insertArea) - { - found = true; - break; - } - } - Assert.IsTrue(found); - - // - areas = region.GetAreasOfSpot(1499, 1000, 2000); - Assert.IsTrue(areas.Count > 0); - - found = false; - foreach (IArea ar in areas) - { - if (ar == insertArea) - { - found = true; - break; - } - } - Assert.IsTrue(found); - - - //Notify test - notified = false; - - GamePlayer player = CreateMockGamePlayer(); - - insertArea.RegisterPlayerEnter(new DOLEventHandler(NotifyTest)); - insertArea.OnPlayerEnter(player); - - Assert.IsTrue(notified); - - region.RemoveArea(insertArea); - - areas = region.GetAreasOfSpot(1499, 1000, 2000); - Assert.IsTrue(areas.Count == 0); - - } - - public static void NotifyTest(DOLEvent e, object sender, EventArgs args) - { - Console.WriteLine("notified"); - notified = true; - } - - [Test] - public void RemoveObject() - { - } - } + [TestFixture] + public class RegionTest : ServerTests + { + public static bool notified = false; + + public RegionTest() + { + } + + [Test, Explicit] + public void AddObject() + { + GameObject obj = new GameNPC(); + obj.Name="TestObject"; + obj.Position = Position.Create(regionID: 1, x: 400000, y: 200000, z: 2000); + + obj.AddToWorld(); + + if (obj.ObjectID<0) + Assert.Fail("Failed to add object to Region. ObjectId < 0"); + + Assert.AreEqual(obj.CurrentRegion.GetObject((ushort)obj.ObjectID),obj); + } + + + [Test, Explicit] + public void AddArea() + { + Region region = WorldMgr.GetRegion(1); + var circleLocation = Coordinate.Create(1000,1000,0); + IArea insertArea = region.AddArea(new Area.Circle(null,circleLocation,500)); + + Assert.IsNotNull(insertArea); + + var areas = region.GetAreasOfSpot(Coordinate.Create(501,1000,0)); + Assert.IsTrue(areas.Count>0); + + bool found = false; + foreach( IArea ar in areas) + { + if (ar == insertArea) + { + found = true; + break; + } + } + Assert.IsTrue(found); + + // + areas = region.GetAreasOfSpot(Coordinate.Create(1499,1000,2000)); + Assert.IsTrue(areas.Count>0); + + found = false; + foreach( IArea ar in areas) + { + if (ar == insertArea) + { + found = true; + break; + } + } + Assert.IsTrue(found); + + + //Notify test + notified=false; + + GamePlayer player = CreateMockGamePlayer(); + + insertArea.RegisterPlayerEnter(new DOLEventHandler(NotifyTest)); + insertArea.OnPlayerEnter(player); + + Assert.IsTrue(notified); + + region.RemoveArea(insertArea); + + areas = region.GetAreasOfSpot(Coordinate.Create(1499,1000,2000)); + Assert.IsTrue(areas.Count==0); + + } + + public static void NotifyTest(DOLEvent e, object sender, EventArgs args) + { + Console.WriteLine("notified"); + notified = true; + } + + [Test] + public void RemoveObject() + { + } + } } diff --git a/Tests/IntegrationTests/TestPacketLib.cs b/Tests/IntegrationTests/TestPacketLib.cs index 1bf3c5a3..dfacd16c 100644 --- a/Tests/IntegrationTests/TestPacketLib.cs +++ b/Tests/IntegrationTests/TestPacketLib.cs @@ -25,9 +25,9 @@ using DOL.GS.Quests; using DOL.Database; using DOL.AI.Brain; +using DOL.GS.Geometry; using DOL.GS.Keeps; using DOL.GS.Housing; -using System.Numerics; using DOL.GS.Profession; namespace DOL.Tests @@ -628,11 +628,11 @@ public void SendChangeTarget(GameObject newTarget) { if (SendChangeTargetMethod != null) SendChangeTargetMethod(this, newTarget); } - public Action SendChangeGroundTargetMethod { get; set; } - public void SendChangeGroundTarget(Vector3 newTarget) - { - if (SendChangeGroundTargetMethod != null) SendChangeGroundTargetMethod(this, newTarget); - } + public Action SendChangeGroundTargetMethod { get; set; } + [Obsolete("Use .SendChangeGroundTarget(Coordinate) instead!")] + public void SendChangeGroundTarget(System.Numerics.Vector3 newTarget) + => SendChangeGroundTarget(Coordinate.Create((int)newTarget.X, (int)newTarget.Y, (int)newTarget.Z)); + public void SendChangeGroundTarget(Coordinate newTarget) => SendChangeGroundTargetMethod?.Invoke(this, newTarget); public Action SendPetWindowMethod { get; set; } public void SendPetWindow(GameLiving pet, ePetWindowAction windowAction, eAggressionState aggroState, eWalkState walkState) { @@ -689,6 +689,7 @@ public void SendLivingDataUpdate(GameLiving living, bool updateStrings) if (SendLivingDataUpdateMethod != null) SendLivingDataUpdateMethod(this, living, updateStrings); } public Action SendSoundEffectMethod { get; set; } + public void SendSoundEffect(ushort soundId, Position position, ushort radius) { } public void SendSoundEffect(ushort soundId, ushort zoneId, ushort x, ushort y, ushort z, ushort radius) { if (SendSoundEffectMethod != null) SendSoundEffectMethod(this, soundId, zoneId, x, y, z, radius); @@ -914,6 +915,10 @@ public void SendMinotaurRelicMapRemove(byte id) if (SendMinotaurRelicMapRemoveMethod != null) SendMinotaurRelicMapRemoveMethod(this, id); } public Action SendMinotaurRelicMapUpdateMethod { get; set; } + public void SendMinotaurRelicMapUpdate(byte id, Position position) + { + if (SendMinotaurRelicMapUpdateMethod != null) SendMinotaurRelicMapUpdateMethod(this, id, position.RegionID, position.X, position.Y, position.Z); + } public void SendMinotaurRelicMapUpdate(byte id, ushort region, int x, int y, int z) { if (SendMinotaurRelicMapUpdateMethod != null) SendMinotaurRelicMapUpdateMethod(this, id, region, x, y, z); diff --git a/Tests/UnitTests/Geometry/UT_Angle.cs b/Tests/UnitTests/Geometry/UT_Angle.cs new file mode 100644 index 00000000..b4e1d247 --- /dev/null +++ b/Tests/UnitTests/Geometry/UT_Angle.cs @@ -0,0 +1,92 @@ +using System; +using NUnit.Framework; +using DOL.GS.Geometry; + +namespace DOL.UnitTests; + +[TestFixture] +public class UT_Angle +{ + [Test] + public void Equals_TwoNewAnglesWithZeroDegrees_True() + { + var angleA = Angle.Degrees(0); + var angleB = Angle.Degrees(0); + + Assert.That(angleA.Equals(angleB), Is.True); + } + + [Test] + public void Equals_TwoDifferentAngles_False() + { + var angleA = Angle.Degrees(0); + var angleB = Angle.Degrees(1); + + Assert.That(angleA.Equals(angleB), Is.False); + } + + [Test] + public void Equals_MinusOneDegreesAnd359Degrees_True() + { + var angleA = Angle.Degrees(-1); + var angleB = Angle.Degrees(359); + + Assert.That(angleA.Equals(angleB), Is.True); + } + + [Test] + public void Heading_One_InHeadingIsOne() + { + var angle = Angle.Heading(1); + + var expected = 1; + var actual = angle.InHeading; + Assert.That(actual, Is.EqualTo(expected)); + } + + [Test] + public void Degrees_One_InDegreesIsOne() + { + var angle = Angle.Heading(1); + + var expected = 1; + var actual = angle.InHeading; + Assert.That(actual, Is.EqualTo(expected)); + } + + [Test] + public void PlusOperator_OneHeadingWithOneHeading_TwoHeading() + { + var actual = Angle.Heading(1) + Angle.Heading(1); + + var expected = Angle.Heading(2); + Assert.That(actual, Is.EqualTo(expected)); + } + + [Test] + public void MinusOperator_OneHeadingMinusOneHeading_AngleZero() + { + var actual = Angle.Heading(1) - Angle.Heading(1); + + var expected = Angle.Zero; + Assert.That(actual, Is.EqualTo(expected)); + } + + [Test] + public void Radians_One2048thPi_OneHeading() + { + var actual = Angle.Radians(Math.PI/2048); + + var expected = Angle.Heading(1); + Assert.That(actual, Is.EqualTo(expected)); + } + + [Test] + public void Radians_One180thPi_OneDegree() + { + var actual = Angle.Radians(Math.PI/180); + + var expected = Angle.Degrees(1); + Assert.That(actual, Is.EqualTo(expected)); + } +} diff --git a/Tests/UnitTests/Geometry/UT_Motion.cs b/Tests/UnitTests/Geometry/UT_Motion.cs new file mode 100644 index 00000000..50b39148 --- /dev/null +++ b/Tests/UnitTests/Geometry/UT_Motion.cs @@ -0,0 +1,44 @@ +using DOL.GS.Geometry; +using NUnit.Framework; + +namespace DOL.UnitTests; + +[TestFixture] +public class UT_Motion +{ + [Test] + public void GetLocationAfter_Zero_Start() + { + var start = Position.Zero; + + var actual = Motion.Create(start, destination: Coordinate.Nowhere, withSpeed: 0) + .GetPositonAfter(0); + + Assert.That(actual, Is.EqualTo(start)); + } + + [Test] + public void GetLocationAfter_FromZeroAfter1000MilliSecondsWithSpeed100AndOrientationZero_Plus100Y() + { + var start = Position.Zero; + var motion = Motion.Create(start, destination: Coordinate.Nowhere, withSpeed: 100); + + var actual = motion.GetPositonAfter(1000); + + var expected = start + Vector.Create(y: 100); + Assert.That(actual, Is.EqualTo(expected)); + } + + [Test] + public void GetLocationAfter_FromZeroAfter1000MilliSecondsWithSpeed100AndOrientationZeroAndDestination50Y_Destination() + { + var start = Position.Zero; + var destination = start + Vector.Create(y: 50); + var motion = Motion.Create(start, destination.Coordinate, withSpeed: 100); + + var actual = motion.GetPositonAfter(1000); + + var expected = destination; + Assert.That(actual, Is.EqualTo(destination)); + } +} diff --git a/Tests/UnitTests/Geometry/UT_Vector.cs b/Tests/UnitTests/Geometry/UT_Vector.cs new file mode 100644 index 00000000..5821c7f1 --- /dev/null +++ b/Tests/UnitTests/Geometry/UT_Vector.cs @@ -0,0 +1,115 @@ +using System; +using DOL.GS.Geometry; +using NUnit.Framework; + +namespace DOL.UnitTests; + +[TestFixture] +public class UT_Vector +{ + [Test] + public void Equals_TwoNewVectors_True() + { + var vectorA = Vector.Create(); + var vectorB = Vector.Create(); + + Assert.That(vectorA.Equals(vectorB), Is.True); + } + + [Test] + public void Equals_VectorWithDifferentX_False() + { + var vectorA = Vector.Create(x: 0); + var vectorB = Vector.Create(x: 1); + + Assert.That(vectorA.Equals(vectorB), Is.False); + } + + [Test] + public void PlusOperator_TwoVectorsWithLengthOne_VectorWithLength2() + { + var vector = Vector.Create(orientation: Angle.Zero, length: 1); + + var actual = (vector + vector).Length; + + var expectedLength = 2; + Assert.That(actual, Is.EqualTo(expectedLength)); + } + + [Test] + public void Create_OrientationZeroWithLengthOne_SameAsVectorWithYOne() + { + var actual = Vector.Create(orientation: Angle.Zero, length: 1); + + var expected = Vector.Create(y: 1); + Assert.That(actual, Is.EqualTo(expected)); + } + + [Test] + public void Create_Orientation45DegreesWithLengthOneHundred_VectorWithXMinus71AndY71() + { + var actual = Vector.Create(orientation: Angle.Degrees(45), length: 100); + + var expected = Vector.Create(x: -71, y: 71); + Assert.That(actual, Is.EqualTo(expected)); + } + + [Test] + public void RotatedClockwise_VectorXOneHundredBy90Degrees_VectorWithYOneHundred() + { + var vector = Vector.Create(x: 100); + + var actual = vector.RotatedClockwise(Angle.Degrees(90)); + + var expected = Vector.Create(y: 100); + Assert.That(actual, Is.EqualTo(expected)); + } + + [Test] + public void RotatedClockwise_VectorXOneHundredBy45Degrees_VectorWithX71AndY71() + { + var vector = Vector.Create(x: 100); + + var actual = vector.RotatedClockwise(Angle.Degrees(45)); + + //rounded + var expected = Vector.Create(x: 71, y: 71); + Assert.That(actual, Is.EqualTo(expected)); + } + + [Test] + public void RotatedClockwise_VectorX50By45Degrees_VectorWithX35AndY35() + { + var vector = Vector.Create(x: 50); + + var actual = vector.RotatedClockwise(Angle.Degrees(45)); + + //rounded + var expected = Vector.Create(x: 35, y: 35); + Assert.That(actual, Is.EqualTo(expected)); + } + + + + [Test] + public void Length_VectorX1Y2Z2_3() + { + var vector = Vector.Create(x: 1, y: 2, z: 2); + + var actual = vector.Length; + + var expected = 3d; + Assert.That(actual, Is.EqualTo(expected)); + } + + [Test] + public void Length2D_VectorX3Y4Z100_5() + { + var vector = Vector.Create(x: 3, y: 4, z: 100); + + var actual = vector.Length2D; + + var expected = 5d; + Assert.That(actual, Is.EqualTo(expected)); + } +}