示例#1
0
        public double GetUserStepHeight(Vector2 Position)
        {
            RoomTileEffect Effect = mTileEffects [Position.X, Position.Y];

            double Height = mStackHeight [Position.X, Position.Y];

            if (Effect.InteractionHeight >= 0)
            {
                Height -= mStackTopItemHeight [Position.X, Position.Y];
            }

            return(Height);
        }
示例#2
0
        public void UpdateActorStatus(RoomActor Actor)
        {
            Vector2 Redirection = mRedirectGrid[Actor.Position.X, Actor.Position.Y];

            if (Redirection != null)
            {
                Actor.Position = new Vector3(Redirection.X, Redirection.Y, GetUserStepHeight(Redirection));
            }

            RoomTileEffect Effect = mTileEffects[Actor.Position.X, Actor.Position.Y];

            if (Effect == null)
            {
                return;
            }

            Dictionary <string, string> CurrentStatusses = Actor.UserStatusses;

            if (Effect.Type == RoomTileEffectType.Sit && !CurrentStatusses.ContainsKey("mv"))
            {
                string OldStatus = (CurrentStatusses.ContainsKey("sit") ? CurrentStatusses["sit"] : string.Empty);
                string NewStatus = Math.Round(Effect.InteractionHeight, 1).ToString().Replace(',', '.');

                if (Actor.BodyRotation != Effect.Rotation)
                {
                    Actor.BodyRotation = Effect.Rotation;
                    Actor.HeadRotation = Effect.Rotation;
                    Actor.UpdateNeeded = true;
                }

                if (NewStatus != OldStatus)
                {
                    Actor.SetStatus("sit", NewStatus);
                    Actor.UpdateNeeded = true;
                }
            }
            else if (CurrentStatusses.ContainsKey("sit"))
            {
                Actor.RemoveStatus("sit");
                Actor.UpdateNeeded = true;
            }

            if (Effect.Type == RoomTileEffectType.Lay && !CurrentStatusses.ContainsKey("mv"))
            {
                string OldStatus = (CurrentStatusses.ContainsKey("lay") ? CurrentStatusses["lay"] : string.Empty);
                string NewStatus = Math.Round(Effect.InteractionHeight, 1).ToString().Replace(',', '.');

                if (Actor.BodyRotation != Effect.Rotation)
                {
                    Actor.BodyRotation = Effect.Rotation;
                    Actor.HeadRotation = Effect.Rotation;
                    Actor.UpdateNeeded = true;
                }

                if (OldStatus != NewStatus)
                {
                    Actor.SetStatus("lay", NewStatus);
                    Actor.UpdateNeeded = true;
                }
            }
            else if (CurrentStatusses.ContainsKey("lay"))
            {
                Actor.RemoveStatus("lay");
                Actor.UpdateNeeded = true;
            }

            if (Effect.Type == RoomTileEffectType.Effect)
            {
                if ((Actor.AvatarEffectId != Effect.EffectId || !Actor.AvatarEffectByItem))
                {
                    Actor.ApplyEffect(Effect.EffectId, true, true);
                }
            }
            else if (Actor.AvatarEffectByItem)
            {
                int ClearEffect = 0;

                if (Actor.Type == RoomActorType.UserCharacter)
                {
                    Session SessionObject = SessionManager.GetSessionByCharacterId(Actor.ReferenceId);

                    if (SessionObject != null)
                    {
                        ClearEffect = SessionObject.CurrentEffect;
                    }
                }
                else
                {
                    Bot BotObject = (Bot)Actor.ReferenceObject;

                    if (BotObject != null)
                    {
                        ClearEffect = BotObject.Effect;
                    }
                }

                Actor.ApplyEffect(ClearEffect, true, true);
            }

            if (Actor.Type == RoomActorType.UserCharacter && Effect.QuestData > 0)
            {
                Session SessionObject = SessionManager.GetSessionByCharacterId(Actor.ReferenceId);

                if (SessionObject != null)
                {
                    QuestManager.ProgressUserQuest(SessionObject, QuestType.EXPLORE_FIND_ITEM, Effect.QuestData);
                }
            }
        }
示例#3
0
        public void PerformUpdate(object state)
        {
            //Console.WriteLine(Thread.CurrentThread.ManagedThreadId); // use this only to debug threadpooling...

            List <RoomActor> ActorsToUpdate = new List <RoomActor> ();
            List <RoomActor> ActorsToRemove = new List <RoomActor> ();

            // Copy collection
            Dictionary <uint, RoomActor> ActorsCopy = new Dictionary <uint, RoomActor> ();

            List <RoomActor>[,] NewUserGrid = new List <RoomActor> [mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];

            lock (mActorSyncRoot) {
                foreach (KeyValuePair <uint, RoomActor> CopyItem in mActors)
                {
                    ActorsCopy.Add(CopyItem.Key, CopyItem.Value);
                }
            }

            foreach (RoomActor Actor in ActorsCopy.Values)
            {
                // If the room is unloaded, allow no actors
                if (mUnloaded)
                {
                    ActorsToRemove.Add(Actor);
                    continue;
                }

                // The idle time is increased in every step.
                if (Actor.Type == RoomActorType.UserCharacter)
                {
                    Actor.IncreaseIdleTime(Actor.ReferenceId == Info.OwnerId);
                }

                // If this is a bot, allow the brain to process this update tick.
                if (Actor.Type == RoomActorType.AiBot)
                {
                    ((Bot)Actor.ReferenceObject).Brain.PerformUpdate(this);
                }

                // Remove any walking statusses (they will be re-applied below if neccessary)
                if (Actor.UserStatusses.ContainsKey("mv"))
                {
                    Actor.RemoveStatus("mv");
                    Actor.UpdateNeeded = true;
                }

                // Update actor position if neccessary
                if (Actor.PositionToSet != null)
                {
                    // Check if the new position is in the door
                    if (Actor.Type == RoomActorType.UserCharacter && Actor.PositionToSet.X == mCachedModel.DoorPosition.X && Actor.PositionToSet.Y == mCachedModel.DoorPosition.Y)
                    {
                        ActorsToRemove.Add(Actor);
                        continue;
                    }

                    // Update the actual position
                    Actor.Position      = new Vector3(Actor.PositionToSet.X, Actor.PositionToSet.Y, (Math.Round(GetUserStepHeight(Actor.PositionToSet), 1)));
                    Actor.PositionToSet = null;

                    // Handle any "MoveToAndInteract" events if this was the last step
                    if (!Actor.IsMoving && Actor.MoveToAndInteract > 0 && Actor.Type == RoomActorType.UserCharacter)
                    {
                        Item Item = GetItem(Actor.MoveToAndInteract);

                        if (Item != null)
                        {
                            ItemEventDispatcher.InvokeItemEventHandler(SessionManager.GetSessionByCharacterId(
                                                                           Actor.ReferenceId), Item, this, ItemEventType.Interact, Actor.MoveToAndInteractData);
                        }

                        Actor.MoveToAndInteract = 0;
                    }
                }

                // If there are more steps to be made, handle it.
                if (Actor.IsMoving)
                {
                    // Check if moving to door
                    if (!Actor.IsLeavingRoom && Actor.Pathfinder.Target.X == mCachedModel.DoorPosition.X &&
                        Actor.Pathfinder.Target.Y == mCachedModel.DoorPosition.Y)
                    {
                        Actor.IsLeavingRoom = true;
                    }

                    // Get the next step from the pathfinder
                    Vector2 NextStep = Actor.GetNextStep();

                    // If the user is leaving and has exceeded 11 steps, help him out by instantly
                    // removing them.
                    if (Actor.LeaveStepsTaken >= 11)
                    {
                        ActorsToRemove.Add(Actor);
                        continue;
                    }

                    // If the pathfinder reports no more steps to be made, this is the last step.
                    bool LastStep = !Actor.IsMoving;

                    // Check that the next step is valid and allowed
                    if (NextStep != null && ((!Actor.ClippingEnabled && IsValidPosition(NextStep)) ||
                                             IsValidStep(Actor.Position.GetVector2(), NextStep, LastStep, NewUserGrid)))
                    {
                        // Update "mv" status
                        Actor.SetStatus("mv", NextStep.X + "," + NextStep.Y + "," + (Math.Round(GetUserStepHeight(NextStep), 1)).ToString().Replace(',', '.'));
                        Actor.PositionToSet = NextStep;

                        // Update new/temporary grid with our new move to position
                        if (NewUserGrid [NextStep.X, NextStep.Y] == null)
                        {
                            NewUserGrid [NextStep.X, NextStep.Y] = new List <RoomActor> ();
                        }

                        NewUserGrid [NextStep.X, NextStep.Y].Add(Actor);

                        // Remove any "sit" statusses
                        if (Actor.UserStatusses.ContainsKey("sit"))
                        {
                            Actor.RemoveStatus("sit");
                        }

                        // Remove any "lay" statusses
                        if (Actor.UserStatusses.ContainsKey("lay"))
                        {
                            Actor.RemoveStatus("lay");
                        }

                        // Update rotation
                        if (Actor.WalkingBackwards)
                        {
                            Actor.BodyRotation = Rotation.CalculateBackwards(Actor.Position.GetVector2(), NextStep);
                        }
                        else
                        {
                            Actor.BodyRotation = Rotation.Calculate(Actor.Position.GetVector2(), NextStep);
                        }
                        Actor.HeadRotation = Actor.BodyRotation;

                        RoomTileEffect Effect = mTileEffects [NextStep.X, NextStep.Y];


                        uint WiredId = mWiredManager.GetRegisteredWalkItem(mFurniMap[NextStep.X, NextStep.Y]);
                        Item Wired   = GetItem(WiredId);
                        if (Wired != null && Wired.Definition.Behavior == ItemBehavior.WiredTrigger)
                        {
                            if (WiredTypesUtil.TriggerFromInt(Wired.Definition.BehaviorData) == WiredTriggerTypes.walks_on_furni && Actor.FurniOnId != mFurniMap[NextStep.X, NextStep.Y])
                            {
                                mWiredManager.ExecuteActions(Wired, Actor);
                            }
                        }

                        WiredId = mWiredManager.GetRegisteredWalkItem(mFurniMap[Actor.Position.X, Actor.Position.Y]);
                        Wired   = GetItem(WiredId);
                        if (Wired != null && Wired.Definition.Behavior == ItemBehavior.WiredTrigger)
                        {
                            if (WiredTypesUtil.TriggerFromInt(Wired.Definition.BehaviorData) == WiredTriggerTypes.walks_off_furni && Actor.FurniOnId != mFurniMap[NextStep.X, NextStep.Y])
                            {
                                mWiredManager.ExecuteActions(Wired, Actor);
                            }
                        }

                        Actor.FurniOnId = mFurniMap[NextStep.X, NextStep.Y];

                        // Request update for next @B cycle
                        Actor.UpdateNeeded = true;
                    }
                    else
                    {
                        // Invalid step: tell pathfinder to stop and mark current position on temporary grid
                        Vector2 target = Actor.Pathfinder.Target;

                        Actor.StopMoving();
                        if (NewUserGrid [NextStep.X, NextStep.Y] == null)
                        {
                            NewUserGrid [NextStep.X, NextStep.Y] = new List <RoomActor> ();
                        }

                        NewUserGrid [NextStep.X, NextStep.Y].Add(Actor);
                        if (ConfigManager.GetValue("pathfinder.mode").ToString().ToLower() == "simple_redirect")
                        {
                            Actor.MoveTo(new Vector2(NextStep.X - 1, NextStep.Y));                               // Redirect???
                            while (Actor.IsMoving)
                            {
                            }
                            Actor.MoveTo(target);
                        }
                    }
                }
                else
                {
                    if (NewUserGrid [Actor.Position.X, Actor.Position.Y] == null)
                    {
                        NewUserGrid [Actor.Position.X, Actor.Position.Y] = new List <RoomActor> ();
                    }

                    NewUserGrid [Actor.Position.X, Actor.Position.Y].Add(Actor);
                }

                // If the actor is leaving and has stopped walking, help them out by removing them.
                if (!Actor.IsMoving && Actor.IsLeavingRoom && Actor.Type == RoomActorType.UserCharacter)
                {
                    ActorsToRemove.Add(Actor);
                    continue;
                }

                // Update status (apply any sit/lay/effect)
                UpdateActorStatus(Actor);

                // Add this actor to the update list if this has been requested
                if (Actor.UpdateNeeded)
                {
                    ActorsToUpdate.Add(Actor);
                    Actor.UpdateNeeded = false;
                }
            }

            // Remove all actors that need to be removed
            foreach (RoomActor Actor in ActorsToRemove)
            {
                lock (mActorSyncRoot) {
                    if (ActorsToUpdate.Contains(Actor))
                    {
                        ActorsToUpdate.Remove(Actor);
                    }
                }

                switch (Actor.Type)
                {
                default:

                    RemoveActorFromRoom(Actor.Id);
                    break;

                case RoomActorType.UserCharacter:

                    HardKickUser(Actor.ReferenceId);
                    break;
                }
            }

            // Send update list (if there are any updates) to room
            if (ActorsToUpdate.Count > 0)
            {
                BroadcastMessage(RoomUserStatusListComposer.Compose(ActorsToUpdate));
            }

            // Update tick on all items --
            List <Item> ItemCopy = null;

            lock (mItemSyncRoot) {
                ItemCopy = mItems.Values.ToList();
            }

            foreach (Item Item in ItemCopy)
            {
                Item.Update(this);
            }

            // Invalidate door position
            NewUserGrid [mCachedModel.DoorPosition.X, mCachedModel.DoorPosition.Y] = null;

            // Update user grid to our new version
            lock (mActorSyncRoot) {
                mUserGrid = NewUserGrid;
            }

            if (mMusicController != null && mMusicController.IsPlaying)
            {
                mMusicController.Update(this);
            }
        }
示例#4
0
        /// <summary>
        /// (Re)generates the relative heightmap for this room. Neccessary after furniture updates.
        /// </summary>
        public void RegenerateRelativeHeightmap(bool Broadcast = false)
        {
            lock (mItems) {
                mGuestsCanPlaceStickies = false;

                mFurniMap           = new uint[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];
                mStackHeight        = new double[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];
                mStackTopItemHeight = new double[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];
                mUserMovementNodes  = new UserMovementNode[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];
                mTileEffects        = new RoomTileEffect[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];
                mRedirectGrid       = new Vector2[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];

                for (int y = 0; y < mCachedModel.Heightmap.SizeY; y++)
                {
                    for (int x = 0; x < mCachedModel.Heightmap.SizeX; x++)
                    {
                        mStackHeight [x, y]        = mCachedModel.Heightmap.FloorHeight [x, y];
                        mStackTopItemHeight [x, y] = 0;
                        mUserMovementNodes [x, y]  = UserMovementNode.Walkable;
                        mTileEffects [x, y]        = new RoomTileEffect();
                        mRedirectGrid [x, y]       = null;
                    }
                }

                bool[,] AnyItemInStack = new bool[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];

                foreach (Item Item in mItems.Values)
                {
                    if (Item.Definition.StackingBehavior == ItemStackingBehavior.Ignore)
                    {
                        continue;
                    }

                    double         TotalItemStackHeight = Item.RoomPosition.Z + Math.Round(Item.Definition.Height, 1);
                    List <Vector2> AffectedTiles        = CalculateAffectedTiles(Item, Item.RoomPosition.GetVector2(), Item.RoomRotation);

                    RoomTileEffect   Effect       = new RoomTileEffect();
                    UserMovementNode MovementNode = UserMovementNode.Blocked;

                    switch (Item.Definition.Behavior)
                    {
                    case ItemBehavior.Seat:
                    case ItemBehavior.LoveShuffler:

                        Effect = new RoomTileEffect(RoomTileEffectType.Sit, Item.RoomRotation,
                                                    new Vector2(Item.RoomPosition.X, Item.RoomPosition.Y), Item.Definition.Height, 0,
                                                    Item.DefinitionId);
                        MovementNode = UserMovementNode.WalkableEndOfRoute;
                        break;

                    case ItemBehavior.Bed:

                        Effect = new RoomTileEffect(RoomTileEffectType.Lay, Item.RoomRotation,
                                                    new Vector2(Item.RoomPosition.X, Item.RoomPosition.Y), Item.Definition.Height, 0,
                                                    Item.DefinitionId);
                        MovementNode = UserMovementNode.WalkableEndOfRoute;
                        break;

                    case ItemBehavior.Gate:

                        MovementNode = Item.Flags == "1" ? UserMovementNode.Walkable : UserMovementNode.Blocked;
                        break;

                    case ItemBehavior.AvatarEffectGenerator:

                        Effect = new RoomTileEffect(RoomTileEffectType.Effect, 0, Item.RoomPosition.GetVector2(), 0,
                                                    Item.Definition.BehaviorData, Item.DefinitionId);
                        break;

                    case ItemBehavior.StickyPole:

                        mGuestsCanPlaceStickies = true;
                        break;
                    }

                    foreach (Vector2 Tile in AffectedTiles)
                    {
                        if (TotalItemStackHeight >= mStackHeight [Tile.X, Tile.Y])
                        {
                            if (Item.Definition.Walkable == ItemWalkableMode.Always)
                            {
                                MovementNode = UserMovementNode.Walkable;
                            }
                            else if (Item.Definition.Walkable == ItemWalkableMode.Limited)
                            {
                                MovementNode = (AnyItemInStack [Tile.X, Tile.Y] && mUserMovementNodes [Tile.X, Tile.Y] != UserMovementNode.Walkable) ? UserMovementNode.Blocked : UserMovementNode.Walkable;
                            }

                            mStackHeight [Tile.X, Tile.Y]        = TotalItemStackHeight;
                            mStackTopItemHeight [Tile.X, Tile.Y] = Item.Definition.Height;
                            mUserMovementNodes [Tile.X, Tile.Y]  = MovementNode;
                            mTileEffects [Tile.X, Tile.Y]        = Effect;
                            mFurniMap [Tile.X, Tile.Y]           = Item.Id;

                            if (Item.Definition.Behavior == ItemBehavior.Bed)
                            {
                                if (Item.RoomRotation == 2 || Item.RoomRotation == 6)
                                {
                                    mRedirectGrid [Tile.X, Tile.Y] = new Vector2(Item.RoomPosition.X, Tile.Y);
                                }

                                if (Item.RoomRotation == 0 || Item.RoomRotation == 4)
                                {
                                    mRedirectGrid [Tile.X, Tile.Y] = new Vector2(Tile.X, Item.RoomPosition.Y);
                                }
                            }
                            else
                            {
                                mRedirectGrid [Tile.X, Tile.Y] = null;
                            }

                            AnyItemInStack [Tile.X, Tile.Y] = true;
                        }
                    }
                }

                foreach (StaticObject Object in mStaticObjects)
                {
                    mStackHeight [Object.Position.X, Object.Position.Y]        = mCachedModel.Heightmap.FloorHeight [Object.Position.X, Object.Position.Y] + 1.0;
                    mStackTopItemHeight [Object.Position.X, Object.Position.Y] = 1.0;
                    mUserMovementNodes [Object.Position.X, Object.Position.Y]  = (Object.IsSeat ? UserMovementNode.WalkableEndOfRoute : UserMovementNode.Blocked);

                    if (Object.IsSeat)
                    {
                        mTileEffects [Object.Position.X, Object.Position.Y] = new RoomTileEffect(RoomTileEffectType.Sit, Object.Rotation, Object.Position, 1.0);
                    }
                }

                lock (mTileStates) {
                    StringBuilder RelativeHeightmap = new StringBuilder();
                    mTileStates = new TileState[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];

                    for (int y = 0; y < mCachedModel.Heightmap.SizeY; y++)
                    {
                        for (int x = 0; x < mCachedModel.Heightmap.SizeX; x++)
                        {
                            if (mInfo.Type == RoomType.Flat && mCachedModel.DoorPosition.X == x && mCachedModel.DoorPosition.Y == y)
                            {
                                mTileStates [x, y] = TileState.Door;
                                RelativeHeightmap.Append(mCachedModel.DoorPosition.Z);
                                continue;
                            }

                            if (mCachedModel.Heightmap.TileStates [x, y] == TileState.Blocked)
                            {
                                mTileStates [x, y] = TileState.Blocked;
                                RelativeHeightmap.Append('x');
                                continue;
                            }

                            mTileStates [x, y] = TileState.Open;
                            RelativeHeightmap.Append(mCachedModel.Heightmap.FloorHeight [x, y]);
                        }

                        RelativeHeightmap.Append(Convert.ToChar(13));
                    }

                    lock (mRelativeHeightmap) {
                        string NewRelativeMap = RelativeHeightmap.ToString();

                        if (NewRelativeMap != mRelativeHeightmap)
                        {
                            mRelativeHeightmap = RelativeHeightmap.ToString();

                            if (Broadcast)
                            {
                                BroadcastMessage(RoomRelativeHeightmapComposer.Compose(mRelativeHeightmap));
                            }
                        }
                    }
                }
            }
        }
示例#5
0
        /// <summary>
        /// (Re)generates the relative heightmap for this room. Neccessary after furniture updates.
        /// </summary>
        public void RegenerateRelativeHeightmap(bool Broadcast = false)
        {
            lock (mItems) {
                mGuestsCanPlaceStickies = false;

                mFurniMap = new uint[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];
                mStackHeight = new double[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];
                mStackTopItemHeight = new double[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];
                mUserMovementNodes = new UserMovementNode[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];
                mTileEffects = new RoomTileEffect[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];
                mRedirectGrid = new Vector2[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];

                for (int y = 0; y < mCachedModel.Heightmap.SizeY; y++) {
                    for (int x = 0; x < mCachedModel.Heightmap.SizeX; x++) {
                        mStackHeight [x, y] = mCachedModel.Heightmap.FloorHeight [x, y];
                        mStackTopItemHeight [x, y] = 0;
                        mUserMovementNodes [x, y] = UserMovementNode.Walkable;
                        mTileEffects [x, y] = new RoomTileEffect ();
                        mRedirectGrid [x, y] = null;
                    }
                }

                bool[,] AnyItemInStack = new bool[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];

                foreach (Item Item in mItems.Values) {
                    if (Item.Definition.StackingBehavior == ItemStackingBehavior.Ignore) {
                        continue;
                    }

                    double TotalItemStackHeight = Item.RoomPosition.Z + Math.Round (Item.Definition.Height, 1);
                    List<Vector2> AffectedTiles = CalculateAffectedTiles (Item, Item.RoomPosition.GetVector2 (), Item.RoomRotation);

                    RoomTileEffect Effect = new RoomTileEffect ();
                    UserMovementNode MovementNode = UserMovementNode.Blocked;

                    switch (Item.Definition.Behavior) {
                    case ItemBehavior.Seat:
                    case ItemBehavior.LoveShuffler:

                        Effect = new RoomTileEffect (RoomTileEffectType.Sit, Item.RoomRotation,
                                new Vector2 (Item.RoomPosition.X, Item.RoomPosition.Y), Item.Definition.Height, 0,
                                Item.DefinitionId);
                        MovementNode = UserMovementNode.WalkableEndOfRoute;
                        break;

                    case ItemBehavior.Bed:

                        Effect = new RoomTileEffect (RoomTileEffectType.Lay, Item.RoomRotation,
                                new Vector2 (Item.RoomPosition.X, Item.RoomPosition.Y), Item.Definition.Height, 0,
                                Item.DefinitionId);
                        MovementNode = UserMovementNode.WalkableEndOfRoute;
                        break;

                    case ItemBehavior.Gate:

                        MovementNode = Item.Flags == "1" ? UserMovementNode.Walkable : UserMovementNode.Blocked;
                        break;

                    case ItemBehavior.AvatarEffectGenerator:

                        Effect = new RoomTileEffect (RoomTileEffectType.Effect, 0, Item.RoomPosition.GetVector2 (), 0,
                                Item.Definition.BehaviorData, Item.DefinitionId);
                        break;

                    case ItemBehavior.StickyPole:

                        mGuestsCanPlaceStickies = true;
                        break;

                    }

                    foreach (Vector2 Tile in AffectedTiles) {
                        if (TotalItemStackHeight >= mStackHeight [Tile.X, Tile.Y]) {
                            if (Item.Definition.Walkable == ItemWalkableMode.Always) {
                                MovementNode = UserMovementNode.Walkable;
                            } else if (Item.Definition.Walkable == ItemWalkableMode.Limited) {
                                MovementNode = (AnyItemInStack [Tile.X, Tile.Y] && mUserMovementNodes [Tile.X, Tile.Y] != UserMovementNode.Walkable) ? UserMovementNode.Blocked : UserMovementNode.Walkable;
                            }

                            mStackHeight [Tile.X, Tile.Y] = TotalItemStackHeight;
                            mStackTopItemHeight [Tile.X, Tile.Y] = Item.Definition.Height;
                            mUserMovementNodes [Tile.X, Tile.Y] = MovementNode;
                            mTileEffects [Tile.X, Tile.Y] = Effect;
                            mFurniMap [Tile.X, Tile.Y] = Item.Id;

                            if (Item.Definition.Behavior == ItemBehavior.Bed) {
                                if (Item.RoomRotation == 2 || Item.RoomRotation == 6) {
                                    mRedirectGrid [Tile.X, Tile.Y] = new Vector2 (Item.RoomPosition.X, Tile.Y);
                                }

                                if (Item.RoomRotation == 0 || Item.RoomRotation == 4) {
                                    mRedirectGrid [Tile.X, Tile.Y] = new Vector2 (Tile.X, Item.RoomPosition.Y);
                                }
                            } else {
                                mRedirectGrid [Tile.X, Tile.Y] = null;
                            }

                            AnyItemInStack [Tile.X, Tile.Y] = true;
                        }
                    }
                }

                foreach (StaticObject Object in mStaticObjects) {
                    mStackHeight [Object.Position.X, Object.Position.Y] = mCachedModel.Heightmap.FloorHeight [Object.Position.X, Object.Position.Y] + 1.0;
                    mStackTopItemHeight [Object.Position.X, Object.Position.Y] = 1.0;
                    mUserMovementNodes [Object.Position.X, Object.Position.Y] = (Object.IsSeat ? UserMovementNode.WalkableEndOfRoute : UserMovementNode.Blocked);

                    if (Object.IsSeat) {
                        mTileEffects [Object.Position.X, Object.Position.Y] = new RoomTileEffect (RoomTileEffectType.Sit, Object.Rotation, Object.Position, 1.0);
                    }
                }

                lock (mTileStates) {
                    StringBuilder RelativeHeightmap = new StringBuilder ();
                    mTileStates = new TileState[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];

                    for (int y = 0; y < mCachedModel.Heightmap.SizeY; y++) {
                        for (int x = 0; x < mCachedModel.Heightmap.SizeX; x++) {
                            if (mInfo.Type == RoomType.Flat && mCachedModel.DoorPosition.X == x && mCachedModel.DoorPosition.Y == y) {
                                mTileStates [x, y] = TileState.Door;
                                RelativeHeightmap.Append (mCachedModel.DoorPosition.Z);
                                continue;
                            }

                            if (mCachedModel.Heightmap.TileStates [x, y] == TileState.Blocked) {
                                mTileStates [x, y] = TileState.Blocked;
                                RelativeHeightmap.Append ('x');
                                continue;
                            }

                            mTileStates [x, y] = TileState.Open;
                            RelativeHeightmap.Append (mCachedModel.Heightmap.FloorHeight [x, y]);
                        }

                        RelativeHeightmap.Append (Convert.ToChar (13));
                    }

                    lock (mRelativeHeightmap) {
                        string NewRelativeMap = RelativeHeightmap.ToString ();

                        if (NewRelativeMap != mRelativeHeightmap) {
                            mRelativeHeightmap = RelativeHeightmap.ToString ();

                            if (Broadcast) {
                                BroadcastMessage (RoomRelativeHeightmapComposer.Compose (mRelativeHeightmap));
                            }
                        }
                    }
                }
            }
        }