/* Thor Server Project Copyright 2008 Joe Hegarty This file is part of The Thor Server Project. The Thor Server Project is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 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 GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with The Thor Server Project. If not, see . */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Timers; using ThorServer.Game.Furni; using ThorServer.Core; using ThorServer.Utilities; using ThorServer.Game.Rooms; using ThorServer.Game.Rooms.Pathfinding; namespace ThorServer.Game.Rooms.Interactor { public partial class RoomInteractor { private StringBuilder mRollerBroadcast = new StringBuilder(); private double mRollerNext = DateTime.Now.TimeOfDay.TotalSeconds + 2; private int mRollerDay = DateTime.Now.DayOfYear; private void HandleRollerActions() { if (mHasRollers) { if (DateTime.Now.TimeOfDay.TotalSeconds > mRollerNext || mRollerDay != DateTime.Now.DayOfYear) { try { List excludeUsers = new List(); List excludeFurni = new List(); foreach (FurniInfo roller in mFloorFurni) { //Is this a roller ? if (roller.Flags.IsRoller) { float rollerOffset = roller.HeightOffset; //Work out next tile int nextX = roller.PosX; int nextY = roller.PosY; if (roller.PosRotation == 0) nextY--; if (roller.PosRotation == 2) nextX++; if (roller.PosRotation == 4) nextY++; if (roller.PosRotation == 6) nextX--; float nextZ = 0; if (ValidTile(nextX, nextY)) { nextX = mRedirectMap[nextX, nextY].X; nextY = mRedirectMap[nextX, nextY].Y; //Get data on current tile RoomUser userCurrent = mRoomInstance.GetUser(roller.PosX, roller.PosY); List furniCurrent = GetFurniObjects(roller.PosX, roller.PosY); //Get data on next tile bool isBlockedNext = !TileCheck(nextX, nextY, mMatrix); List furniNext = GetFurniObjects(nextX, nextY); //Roller on next tile? Can a user sit there? bool isRollerOnNext = false; bool isSitOnNext = false; bool isFloormatOnNext = false; bool overrideDoormat = false; if (furniNext != null) { foreach (FurniInfo fInfo in furniNext) { if (fInfo.Flags.IsRoller) isRollerOnNext = true; if (fInfo.Flags.CanSit || fInfo.Flags.CanLay) { isSitOnNext = true; } if (fInfo.VarType == FurniInfo.VarTypes.DoorDivider) { isBlockedNext = true; } if (fInfo.Flags.Doormat) { isBlockedNext = true; isFloormatOnNext = true; } if (!fInfo.Flags.CanPath) { overrideDoormat = true; } } } //If the next tile is blocked, we can't do anything if (isFloormatOnNext) isFloormatOnNext = !overrideDoormat; bool notUserBlock = (isSitOnNext || isFloormatOnNext) && !isRollerOnNext && !PlayerCheck(nextX, nextY); if (isBlockedNext && !notUserBlock) continue; //Update furni if (furniCurrent != null && !isBlockedNext) { foreach (FurniInfo fInfo in furniCurrent) { if (!fInfo.Flags.IsRoller && !excludeFurni.Contains(fInfo.FurniID)) { nextZ = fInfo.PosZ; if (!isRollerOnNext) nextZ -= rollerOffset; UpdateRollerFurni(fInfo, nextX, nextY, nextZ, !isRollerOnNext, roller.FurniID); mFloorFurni = InstanceManager.Game.Furni.GetRoomFloorFurni(mRoomInstance.RoomInfo.RoomID); GenerateMaps(); excludeFurni.Add(fInfo.FurniID); } } } //Update user if (userCurrent != null) { if (!userCurrent.IsMoving && !excludeUsers.Contains(userCurrent.RoomUserID)) { nextZ = userCurrent.CurrentZ; if (!isRollerOnNext) nextZ -= rollerOffset; UpdateRollerUser(userCurrent, nextX, nextY, nextZ, !isRollerOnNext, roller.FurniID); excludeUsers.Add(userCurrent.RoomUserID); } } } } mRoomInstance.RoomBroadcast(mRollerBroadcast.ToString()); mRollerBroadcast.Remove(0, mRollerBroadcast.Length); mRollerNext = DateTime.Now.TimeOfDay.TotalSeconds + 2; mRollerDay = DateTime.Now.DayOfYear; } } catch (Exception e) { Logging.LogEvent("Roller Error! Disabling rollers in this room. Stack " + e.ToString(), Logging.LogLevel.Error); mHasRollers = false; } } } } private void UpdateRollerFurni(FurniInfo info, int nextX, int nextY, float nextZ, bool isLastRoller, int rollerId) { ClientMessage mMessage = new ClientMessage(); mMessage.Init(230); // Cf mMessage.appendArgumentInt(info.PosX); mMessage.appendArgumentInt(info.PosY); mMessage.appendArgumentInt(nextX); mMessage.appendArgumentInt(nextY); mMessage.appendArgumentInt(1); mMessage.appendArgumentInt(info.FurniID); mMessage.appendString(info.PosZ.ToString().Replace(',', '.')); mMessage.appendChar(2); mMessage.appendString(nextZ.ToString().Replace(',', '.')); mMessage.appendChar(2); mMessage.appendArgumentInt(rollerId); mRollerBroadcast.Append(mMessage.ToString()); info.PosX = nextX; info.PosY = nextY; info.PosZ = nextZ; InstanceManager.Game.Furni.MoveFloorItem(info.FurniID, info.PosX, info.PosY, info.PosZ, info.PosRotation, mRoomInstance.RoomInfo); } private void UpdateRollerUser(RoomUser user, int newX, int newY, float newZ, bool isLastRoller, int rollerId) { user.NextX = newX; user.NextY = newY; user.NextZ = newZ; ClientMessage mMessage = new ClientMessage(); mMessage.Init(230); // Cf mMessage.appendArgumentInt(user.CurrentX); mMessage.appendArgumentInt(user.CurrentY); mMessage.appendArgumentInt(user.NextX); mMessage.appendArgumentInt(user.NextY); mMessage.appendArgumentInt(0); mMessage.appendArgumentInt(rollerId); mMessage.appendString("J"); mMessage.appendArgumentInt(user.RoomUserID); mMessage.appendString(user.CurrentZ.ToString().Replace(',', '.')); mMessage.appendChar(2); mMessage.appendString(user.NextZ.ToString().Replace(',', '.')); mMessage.appendChar(2); mRollerBroadcast.Append(mMessage.ToString()); mPlayerMap[user.CurrentX, user.CurrentY] = false; user.CurrentX = user.NextX; user.CurrentY = user.NextY; user.CurrentZ = user.NextZ; user.MustUpdate = true; mPlayerMap[user.CurrentX, user.CurrentY] = true; if (isLastRoller) { CalculateTileStatusForUser(user.CurrentX, user.CurrentY, user, true); } } } }