using System;
using System.Text;
using System.Data;
using System.Threading;
using System.Collections.Generic;
using Woodpecker.Storage;
using Woodpecker.Specialized.Text;
using Woodpecker.Net.Game.Messages;
using Woodpecker.Game.Items;
using Woodpecker.Game.Items.Pets;
using Woodpecker.Game.Rooms.Units;
using Woodpecker.Game.Rooms.Pathfinding;
namespace Woodpecker.Game.Rooms.Instances
{
public partial class roomInstance
{
#region Fields
private const int rollerDelaySeconds = 2;
///
/// Holds true if there is atleast one roller item in the room.
///
private bool hasRollers;
private double mRollerTimer = DateTime.Now.TimeOfDay.TotalSeconds + rollerDelaySeconds;
private int mRollerDay = DateTime.Today.DayOfYear;
///
/// The total amount of 'roller' items in this room instance.
///
public int rollerAmount
{
get
{
int i = 0;
foreach (floorItem lItem in this.floorItems)
{
if (lItem.Definition.Behaviour.isRoller)
i++;
}
return i;
}
}
#endregion
#region Methods
private void runRollers()
{
if (mRollerTimer > DateTime.Now.TimeOfDay.TotalSeconds && mRollerDay == DateTime.Today.DayOfYear)
return;
StringBuilder Updates = new StringBuilder();
List movedRoomUnitIDs = new List();
List movedItemIDs = new List();
try
{
foreach (floorItem lRoller in this.floorItems)
{
if (!lRoller.Definition.Behaviour.isRoller)
continue; // Not a roller item
#region General
// Workout direction for roller
byte nextX = lRoller.X;
byte nextY = lRoller.Y;
if (lRoller.Rotation == 0)
nextY--;
else if (lRoller.Rotation == 2)
nextX++;
else if (lRoller.Rotation == 4)
nextY++;
else if (lRoller.Rotation == 6)
nextX--;
if (!tileExists(nextX, nextY) || tileBlockedByRoomUnit(nextX, nextY))
continue; // Can't roll off room map / on room unit
#endregion
#region Get objects on current tile and verify
roomUnit pUnit = this.getRoomUnitOnTile(lRoller.X, lRoller.Y); // Get room unit on this roller
List pItems = new List();
foreach (floorItem lItem in this.getFloorItems(lRoller.X, lRoller.Y))
{
if (!lItem.Definition.Behaviour.isRoller && !movedItemIDs.Contains(lItem.ID))
pItems.Add(lItem);
}
if (pUnit != null && (pUnit.Moves || movedRoomUnitIDs.Contains(pUnit.ID)))
{
pUnit = null; // Invalid room unit
}
if (pUnit == null && pItems.Count == 0)
continue; // No items on roller and no room unit aswell
#endregion
// Get items on next tile and perform some checks
bool nextTileIsRoller = false;
bool canMoveItems = (this.gridState[nextX, nextY] == roomTileState.Free);
bool canMoveUnit = canMoveItems;
bool nextTileUnitInteractiveStance = false;
foreach (floorItem lItem in this.getFloorItems(nextX, nextY))
{
if (lItem.Definition.Behaviour.isRoller)
{
nextTileIsRoller = true;
continue;
}
if (lItem.Definition.Behaviour.isSolid)
{
canMoveItems = false;
canMoveUnit = false;
if (lItem.Definition.Behaviour.isDoor)
{
if (lItem.customData == "O") // Door is open
canMoveUnit = true; // Can move unit in door
}
}
else if (pUnit != null && lItem.Definition.isInteractiveStance)
{
nextTileUnitInteractiveStance = true;
if(!nextTileIsRoller)
canMoveUnit = true;
}
}
if (!canMoveItems) // Can't move items
{
if (!canMoveUnit) // Can't move unit aswell
continue; // Can't run this roller
pItems.Clear(); // Clear items to move
}
#region Generate notification and move objects
serverMessage eventNotification = new serverMessage(230); // "Cf"
eventNotification.appendWired(lRoller.X);
eventNotification.appendWired(lRoller.Y);
eventNotification.appendWired(nextX);
eventNotification.appendWired(nextY);
eventNotification.appendWired(pItems.Count);
foreach (floorItem lItem in pItems)
{
float nextZ = lItem.Z;
if (!nextTileIsRoller)
nextZ -= lRoller.Definition.topHeight;
eventNotification.appendWired(lItem.ID);
eventNotification.appendClosedValue(stringFunctions.formatFloatForClient(lItem.Z));
eventNotification.appendClosedValue(stringFunctions.formatFloatForClient(nextZ));
lItem.X = nextX;
lItem.Y = nextY;
lItem.Z = nextZ;
lItem.requiresUpdate = true;
movedItemIDs.Add(lItem.ID);
generateFloorMap();
}
eventNotification.appendWired(lRoller.ID);
if (pUnit != null) // Room unit lifting with roller
{
float nextZ = pUnit.Z;
if (!nextTileIsRoller)
nextZ -= lRoller.Definition.topHeight;
pUnit.X = nextX;
pUnit.Y = nextY;
pUnit.Z = nextZ;
pUnit.requiresUpdate = true;
if (!nextTileIsRoller || nextTileUnitInteractiveStance)
this.setRoomUnitTileState(pUnit);
this.gridUnit[lRoller.X, lRoller.Y] = false;
this.gridUnit[pUnit.X, pUnit.Y] = true;
eventNotification.appendWired(2);
eventNotification.appendWired(pUnit.ID);
eventNotification.appendClosedValue(stringFunctions.formatFloatForClient(pUnit.Z));
eventNotification.appendClosedValue(stringFunctions.formatFloatForClient(nextZ));
movedRoomUnitIDs.Add(pUnit.ID);
}
#endregion
Updates.Append(eventNotification.ToString());
}
if (Updates.Length > 0)
{
this.sendMessage(Updates.ToString());
}
this.mRollerTimer = DateTime.Now.TimeOfDay.TotalSeconds + rollerDelaySeconds;
this.mRollerDay = DateTime.Today.DayOfYear;
}
catch (Exception ex)
{
Core.Logging.Log("Rollers in room instance of room " + this.roomID + " crashed, exception: " + ex.Message);
this.hasRollers = false;
}
}
#endregion
}
}