/* Thor Server 2.0 Project - Codenamed "Stockholm" Copyright 2008 - 2009 Joe Hegarty This file is part of The Thor Server 2.0 Project - Codenamed "Stockholm". The Thor Server 2.0 Project - Codenamed "Stockholm" is free software: you can redistribute it and/or modify it under the terms of the Microsoft Public License The Thor Server Project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Microsoft Public License for more details. You should have received a copy of the Microsoft Public License along with The Thor Server Project. If not, see http://www.opensource.org/licenses/ms-pl.html */ using System; using System.Collections.Generic; using StockholmLibrary.Game.Flats; using StockholmLibrary.Game.Sessions; using StockholmLibrary.Game.Packets.Client; using StockholmLibrary.Game.Packets.Server; using StockholmLibrary.Net; using StockholmLibrary.Util; namespace StockholmLibrary.Game.Entities.Components { //------------------------------------ public class ECCreatureMovement : EntityComponentRoomChild { Queue _path; private object _pathLock = new object(); IsometricPoint _endDestination = new IsometricPoint(); //********************************************** public override void UserInitiailise(Session userSession) { RegisterSessionHandler(userSession, EClientPacket.MOVE, new PacketRoutingInfo.ProcessPacketDelegate(HandleMove)); } //********************************************** public override void UserDeinitiailise(Session userSession) { CleanupSessionHandlers(userSession); } //********************************************** private void HandleMove(ClientPacket packet) { MovePacket movePacket = new MovePacket(); movePacket.Deserialise(packet); MoveTo(movePacket.Location); } //********************************************** public int CalculateNewOrientation(IsometricPoint oldPoint, IsometricPoint newPoint) { //Moved up/down if (oldPoint.X == newPoint.X) { if (oldPoint.Y < newPoint.Y) { //South return 4; } else { return 0; } } //Moved Left else if (oldPoint.X > newPoint.X) { if (oldPoint.Y == newPoint.Y) { return 6; } else if (oldPoint.Y < newPoint.Y) { return 5; } else { return 7; } } //Moved Right else if (oldPoint.X < newPoint.X) { if (oldPoint.Y == newPoint.Y) { return 2; } else if (oldPoint.Y < newPoint.Y) { return 3; } else { return 1; } } return 0; } //********************************************** public override void Pulse() { UpdatePosition(); } //********************************************** private void MoveTo(IsometricPoint point) { ECFlatPhysics flatPhysics = null; if (GetRoomEntity().GetEC(ref flatPhysics)) { lock (_pathLock) { // We need to check if we're already walking as we want to stop popping if (_path != null && _path.Count > 1) { flatPhysics.RemoveEntityFromTile(GetParentEntity(), GetParentEntity().GetPosition()); GetParentEntity().SetPosition(_path.Peek()); } _path = flatPhysics.CalculatePath(GetParentEntity(), point); if (_path == null) { ECCreatureStatus status = null; if (GetParentEntity().GetEC(ref status)) { status.MarkAsDirty(); } } _endDestination.Copy(point); } } } //********************************************** private void UpdatePosition() { ECFlatPhysics flatPhysics = null; if (GetRoomEntity().GetEC(ref flatPhysics)) { lock (_pathLock) { if (_path != null && _path.Count > 0) { Entity creature = GetParentEntity(); IsometricPoint oldPoint = creature.GetPosition(); IsometricPoint nextPoint = _path.Dequeue(); IsometricPoint walkPoint = null; ECCreatureStatus status = null; if (GetParentEntity().GetEC(ref status)) { if (_path.Count > 1) { walkPoint = _path.Peek(); ECFlatPhysics.TileProperties tileProperties = flatPhysics.GetTile(walkPoint); if (!tileProperties.IsPathable && !tileProperties.HasEntity(creature)) { // Retry, this tile is now blocked _path.Clear(); MoveTo(_endDestination); return; } int newOrientation = CalculateNewOrientation(nextPoint, walkPoint); creature.SetOrientation(newOrientation); CreatureStatus.MovementStatus movementStatus = new CreatureStatus.MovementStatus(); movementStatus.Position.Copy(walkPoint); status.AddExtraStatus(movementStatus); } status.MarkAsDirty(); } flatPhysics.RemoveEntityFromTile(creature, oldPoint); flatPhysics.AddEntityToTile(creature, nextPoint); flatPhysics.AddEntityToTile(creature, walkPoint); creature.SetPosition(nextPoint); } } } } } }