/// <summary>
 /// Renders custom objects as held objects for stardew valley machines.
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 public static void Render_RenderCustomObjectsHeldInMachines(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
 {
     if (TrackedMachines.ContainsKey(Game1.player.currentLocation))
     {
         List <SObject> removalList = new List <SObject>();
         foreach (SObject obj in TrackedMachines[Game1.player.currentLocation])
         {
             if (obj.heldObject.Value == null)
             {
                 removalList.Add(obj);
             }
             else
             {
                 if (obj.heldObject.Value is CustomObject)
                 {
                     if (obj.MinutesUntilReady == 0)
                     {
                         float   num = (float)(4.0 * Math.Round(Math.Sin(DateTime.UtcNow.TimeOfDay.TotalMilliseconds / 250.0), 2));
                         Vector2 pos = new Vector2(obj.TileLocation.X * Game1.tileSize, (obj.TileLocation.Y - 1) * Game1.tileSize - 32 + num);
                         obj.heldObject.Value.draw(e.SpriteBatch, (int)pos.X, (int)pos.Y, 0.25f, 1f);
                     }
                 }
             }
         }
         foreach (SObject obj in removalList)
         {
             TrackedMachines[Game1.player.currentLocation].Remove(obj);
         }
     }
 }
예제 #2
0
 private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
 {
     if (!Config.EnableMod)
     {
         return;
     }
     if (locationDict.TryGetValue(Game1.currentLocation.Name, out Dictionary <Point, List <ParticleEffectData> > dict))
     {
         foreach (var kvp in dict)
         {
             foreach (var effect in kvp.Value)
             {
                 ShowLocationParticleEffect(e.SpriteBatch, Game1.currentLocation, effect);
             }
         }
     }
     foreach (var key in effectDict.Keys)
     {
         var ped = effectDict[key];
         switch (ped.type.ToLower())
         {
         case "location":
             if (Game1.currentLocation.Name == ped.name)
             {
                 ShowLocationParticleEffect(e.SpriteBatch, Game1.currentLocation, ped);
             }
             break;
         }
     }
 }
예제 #3
0
 private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
 {
     if (FarmHouseStates.getState(StardewValley.Utility.getHomeOfFarmer(Game1.player)) != null)
     {
         //FarmHouseStates.drawRender(e.SpriteBatch);
         //e.SpriteBatch.Draw(Image.Renderer.testRender, Vector2.Zero, new Rectangle(0, 0, Image.Renderer.testRender.Width, Image.Renderer.testRender.Height), Color.White, 0.0f, Vector2.Zero, 4f, Microsoft.Xna.Framework.Graphics.SpriteEffects.None, 1);
     }
 }
예제 #4
0
 private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
 {
     for (int i = animations.Count - 1; i >= 0; i--)
     {
         animations[i].draw(e.SpriteBatch, false, 0, 0, 1f);
     }
     if (sparklingText != null && lastUser != null)
     {
         sparklingText.draw(e.SpriteBatch, Game1.GlobalToLocal(Game1.viewport, lastUser.Position + new Vector2(-64f, -352f)));
     }
 }
예제 #5
0
 public void drawExtraLayers(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
 {
     if (Pseudo3D.MapHandler.isPseudo3DLocation(Game1.currentLocation))
     {
         Pseudo3D.MapHandler.drawOverlays(e.SpriteBatch, Game1.currentLocation);
     }
     ForegroundHandler.draw(e.SpriteBatch);
     //e.SpriteBatch.End();
     //e.SpriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
     //ParticleHandler.draw(e.SpriteBatch);
     //Perspective.PerspectiveRenderer.draw(e.SpriteBatch);
 }
예제 #6
0
        private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            if (!Context.IsWorldReady)
            {
                return;
            }

            foreach (var t in this._jumpingFish)
            {
                t.Draw(Game1.spriteBatch);
            }
        }
예제 #7
0
        private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            if (!IsModEnabled())
            {
                return;
            }

            if (Config.AsciiEnabled && asciifying)
            {
                int scale = 16;
                var lines = ConvertToAscii(ScaleScreen(scale, out int w, out int h), Game1.graphics.GraphicsDevice.PresentationParameters.BackBufferWidth / scale);
                if (lines.Count > 0)
                {
                    e.SpriteBatch.Draw(blackTexture, new Rectangle(0, 0, Game1.viewport.Width, Game1.viewport.Height), Color.White);
                    int height = Game1.viewport.Height / lines.Count;
                    for (int i = 0; i < lines.Count; i++)
                    {
                        e.SpriteBatch.DrawString(font, lines[i], new Vector2(0, height * i), Color.White, 0, Vector2.Zero, 0.8f, SpriteEffects.None, 1);
                    }
                }
            }
            else if (Config.PixelateEnabled && pixelating)
            {
                Color[]   data        = ScaleScreen(16, out int width, out int height);
                Texture2D pixelScreen = new Texture2D(Game1.graphics.GraphicsDevice, width, height);
                pixelScreen.SetData(data);
                e.SpriteBatch.Draw(pixelScreen, new Rectangle(0, 0, Game1.viewport.Width, Game1.viewport.Height), Color.White);
            }
            if (Config.RavenEnabled && (Game1.timeOfDay >= 2100 || Game1.timeOfDay <= 200))
            {
                for (int i = 0; i < ravenText.Length; i++)
                {
                    var y = Game1.viewport.Height - ravenTicks / 2 + i * 48;
                    if (y < -48)
                    {
                        continue;
                    }
                    if (y > Game1.viewport.Height)
                    {
                        break;
                    }
                    e.SpriteBatch.DrawString(Game1.dialogueFont, ravenText[i], new Vector2(0, y), Color.DarkGray * 0.75f);
                    e.SpriteBatch.DrawString(Game1.dialogueFont, ravenText[i], new Vector2(2, y + 2), Color.Black * 0.75f);
                }
                ravenTicks++;
            }
            else
            {
                ravenTicks = 0;
            }
        }
예제 #8
0
        public void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            if (!Config.EnableMod || !placingTracks || Game1.activeClickableMenu != null)
            {
                return;
            }

            if (placingTracks)
            {
                float layerDepth = (Game1.currentCursorTile.Y * (16 * Game1.pixelZoom) + 16 * Game1.pixelZoom) / 10000f;

                e.SpriteBatch.Draw(trackTexture, Game1.GlobalToLocal(Game1.viewport, Game1.currentCursorTile * 64), new Rectangle(currentTrackIndex * 16, 0, 16, 16), Color.White, 0, Vector2.Zero, 4, SpriteEffects.None, layerDepth);
            }
        }
예제 #9
0
        void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            if (Game1.paused)
            {
                return;
            }

            expAnimations.RemoveAll(anim => anim.Expired());
            expAnimations.ForEach(anim =>
            {
                anim.update(Game1.currentGameTime);
                anim.Draw(e.SpriteBatch);
            });
        }
예제 #10
0
 void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
 {
     foreach (Vector2 vec in CurrentPath)
     {
         e.SpriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, vec * 64f), new Rectangle(194 + 0 * 16, 388, 16, 16), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 0.999f);
     }
     foreach (Vector2 vec in NonPassables)
     {
         e.SpriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, vec * 64f), new Rectangle(194 + 1 * 16, 388, 16, 16), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 0.999f);
     }
     foreach (Vector2 vec in Passables)
     {
         e.SpriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, vec * 64f), new Rectangle(194 + 0 * 16, 388, 16, 16), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 0.999f);
     }
 }
 /// <summary>Draws a hovering excalamation point above each entry in <see cref="ExclamationPointTiles"/> for the current player.</summary>
 private static void RenderedWorld_DrawExclamationPoints(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
 {
     if (!Context.IsPlayerFree)                                                      //if the plyer is NOT free (events, menus, etc)
     {
         return;                                                                     //do nothing
     }
     foreach (ExclamationData point in ExclamationPointTiles.Value)                  //for each exclamation point to draw
     {
         if (!Game1.player.team.acceptedSpecialOrderTypes.Contains(point.OrderType)) //if the players do NOT already have an active order of this type
         {
             //draw the exclamation point (imitate code from Town.draw(SpriteBatch))
             float yOffset = 4f * (float)Math.Round(Math.Sin(Game1.currentGameTime.TotalGameTime.TotalMilliseconds / 250.0), 2);
             e.SpriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, new Vector2(point.PixelPosition.X, point.PixelPosition.Y + yOffset)), SourceRectangle, Color.White, 0f, new Vector2(1f, 4f), 4f + Math.Max(0f, 0.25f - yOffset / 16f), SpriteEffects.None, 1f);
         }
     }
 }
예제 #12
0
        private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            if (Config.EnableMod && framing && frameList.Count > 0)
            {
                var pos = Game1.getMousePosition(false) - Utility.Vector2ToPoint(new Vector2(frameList[currentFrame].texture.Width * 4 / Game1.options.zoomLevel, frameList[currentFrame].texture.Height * 4 / Game1.options.zoomLevel));
                if (pos.X < 0)
                {
                    pos.X = 0;
                }
                if (pos.Y < 0)
                {
                    pos.Y = 0;
                }

                e.SpriteBatch.Draw(frameList[currentFrame].texture, Utility.PointToVector2(pos), null, Color.White, 0, Vector2.Zero, 4 / Game1.options.zoomLevel, SpriteEffects.None, 1);
            }
        }
예제 #13
0
 private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
 {
     if (detachedMenus.Any())
     {
         var back = Game1.options.showMenuBackground;
         Game1.options.showMenuBackground = true;
         foreach (var m in detachedMenus)
         {
             var f = AccessTools.Field(m.GetType(), "drawBG");
             if (f != null)
             {
                 f.SetValue(m, false);
             }
             m.draw(e.SpriteBatch);
         }
         Game1.options.showMenuBackground = back;
     }
 }
예제 #14
0
        private void OnRenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            if (!(Context.IsPlayerFree && !Game1.eventUp && Game1.farmEvent == null && Config.harvestCropsRange > 0 && Config.harvestCrops))
            {
                return;
            }

            if (Config.harvestCrops &&
                Config.harvestCropsRange > 0 &&
                Game1.player.ActiveObject != null &&
                Game1.player.ActiveObject.bigCraftable.Value &&
                Game1.player.ActiveObject.ParentSheetIndex == ItemIds.Autograbber)
            {
                // impl @ StardewValley::Object::drawPlacementBounds
                var placementTile = Game1.GetPlacementGrabTile();
                var X             = (int)placementTile.X;
                var Y             = (int)placementTile.Y;
                if (Game1.IsPerformingMousePlacement())
                {
                    var range = Config.harvestCropsRange;
                    for (int x = X - range; x <= X + range; x++)
                    {
                        for (int y = Y - range; y <= Y + range; y++)
                        {
                            if (Config.harvestCropsRangeMode == "Walk" && Math.Abs(X - x) + Math.Abs(Y - y) > range)
                            {
                                continue;
                            }
                            Game1.spriteBatch.Draw(
                                Game1.mouseCursors,
                                Game1.GlobalToLocal(new Vector2(x, y) * 64),
                                new Rectangle(194, 388, 16, 16),
                                Color.White,
                                0,
                                Vector2.Zero,
                                4,
                                SpriteEffects.None,
                                0.01f
                                );
                        }
                    }
                }
            }
        }
예제 #15
0
 private static void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
 {
     if (Config.EnableMod && Config.PermaDeath && Game1.killScreen)
     {
         deathScreenTimer++;
         if (deathScreenTimer > Config.PermaDeathScreenTicks)
         {
             deathScreenTimer = 0;
             Game1.killScreen = false;
             SHelper.Events.Display.RenderedWorld -= Display_RenderedWorld;
             Game1.ExitToTitle();
         }
         else
         {
             e.SpriteBatch.Draw(blackTexture, new Rectangle(0, 0, Game1.viewport.Width, Game1.viewport.Height), Color.White);
             e.SpriteBatch.DrawString(Game1.dialogueFont, "YOU DIED", new Vector2(Game1.viewport.Width / 2 - Game1.dialogueFont.MeasureString("YOU DIED").X * 4, Game1.viewport.Height / 2 - Game1.dialogueFont.MeasureString("YOU DIED").Y * 4), Color.Red * Math.Min(1, deathScreenTimer / (Config.PermaDeathScreenTicks / 2f)), 0, Vector2.Zero, 8, SpriteEffects.None, 1);
         }
     }
 }
        private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            if (Game1.currentLocation == null)
            {
                return;
            }

            if (_showGrid)
            {
                TileInfoMenu.DrawGrid(e.SpriteBatch, colour: _gridColour, width: _gridWidth, opacity: 1f);
            }

            Point mouse          = Game1.getMousePosition();
            bool  isChildHovered = Desktop.Taskbar.IsExpanded && Desktop.Children.Any(child => child.isWithinBounds(mouse.X, mouse.Y) ||
                                                                                      ((child.GetParentMenu() is WindowBar windowBar) && windowBar.isWithinBounds(mouse.X, mouse.Y)));

            if (_showTileHighlight && !isChildHovered)
            {
                TileInfoMenu.DrawTileHighlight(e.SpriteBatch, colour: _tileHighlightColour);
            }
        }
예제 #17
0
 private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
 {
     if (Config.EnableMod && isBuilding)
     {
         if (Helper.Input.IsDown(Config.BuildKey) || Helper.Input.IsSuppressed(Config.BuildKey))
         {
             buildingRect.Size = Utility.Vector2ToPoint(Game1.lastCursorTile - buildingRect.Location.ToVector2() + new Vector2(1, 1));
             for (int x = buildingRect.X; x < buildingRect.X + buildingRect.Width; x++)
             {
                 for (int y = buildingRect.Y; y < buildingRect.Y + buildingRect.Height; y++)
                 {
                     e.SpriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(new Vector2(x * 64, y * 64)), new Rectangle?(new Rectangle(194, 388, 16, 16)), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 1f);
                 }
             }
             Helper.Input.Suppress(Config.BuildKey);
         }
         else
         {
             BuildBuilding();
             isBuilding   = false;
             buildingRect = new Rectangle();
         }
     }
     else
     {
         isBuilding   = false;
         buildingRect = new Rectangle();
     }
     if (Game1.currentLocation.modData.TryGetValue($"{ModManifest.UniqueID}/index", out string indexString) && indexString.Length > 0)
     {
         string[] parts = indexString.Split('|');
         foreach (var part in parts)
         {
             DrawBuilding(e.SpriteBatch, new ModularBuilding(Game1.currentLocation.modData[$"{ModManifest.UniqueID}/{part}"]));
         }
     }
 }
예제 #18
0
        private static void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            Point mousePos = Game1.getMousePosition();

            if (!phoneOpen)
            {
                appRunning = false;
                runningApp = null;
                if (Game1.activeClickableMenu is MobilePhoneMenu)
                {
                    Game1.activeClickableMenu = null;
                }
                if ((Game1.displayHUD || Game1.eventUp) && Game1.currentBillboard == 0 && Game1.gameMode == 3 && !Game1.freezeControls && !Game1.panMode && !Game1.HostPaused && !Game1.game1.takingMapScreenshot)
                {
                    if (clickingPhoneIcon)
                    {
                        if (SHelper.Input.IsDown(SButton.MouseLeft) && lastMousePosition != mousePos)
                        {
                            draggingPhoneIcon        = true;
                            Config.PhoneIconOffsetX += mousePos.X - lastMousePosition.X;
                            Config.PhoneIconOffsetY += mousePos.Y - lastMousePosition.Y;
                            phoneIconPosition        = GetPhoneIconPosition();
                            lastMousePosition        = mousePos;
                        }
                    }
                    e.SpriteBatch.Draw(iconTexture, phoneIconPosition, Color.White);
                }

                return;
            }

            if (Game1.game1.takingMapScreenshot)
            {
                return;
            }

            if (!appRunning)
            {
                if (Game1.activeClickableMenu == null)
                {
                    Game1.activeClickableMenu = new MobilePhoneMenu();
                }
            }
            else
            {
                if (Game1.activeClickableMenu is MobilePhoneMenu)
                {
                    Game1.activeClickableMenu = null;
                }
            }

            if (draggingPhone)
            {
                if (mousePos != lastMousePosition)
                {
                    int x = mousePos.X - lastMousePosition.X;
                    int y = mousePos.Y - lastMousePosition.Y;
                    if (phoneRotated)
                    {
                        Config.PhoneRotatedOffsetX += x;
                        Config.PhoneRotatedOffsetY += y;
                    }
                    else
                    {
                        Config.PhoneOffsetX += x;
                        Config.PhoneOffsetY += y;
                    }
                    RefreshPhoneLayout();
                    lastMousePosition = mousePos;
                }
            }

            e.SpriteBatch.Draw(phoneRotated ? backgroundRotatedTexture : backgroundTexture, phonePosition, Color.White);
            e.SpriteBatch.Draw(phoneRotated ? phoneRotatedTexture : phoneTexture, phonePosition, Color.White);

            if (appRunning)
            {
                return;
            }

            List <string> keys     = apps.Keys.ToList();
            string        appHover = null;
            bool          hover    = false;

            if (mousePos == lastPos)
            {
                hover = true;
            }
            else
            {
                ticksSinceMoved = 0;
            }

            for (int i = keys.Count - 1; i >= 0; i--)
            {
                if (!IsOnScreen(i, topRow))
                {
                    continue;
                }

                MobileApp app = apps[keys[i]];
                if (app.icon == null)
                {
                    context.Monitor.Log($"no icon for app {app.name}, removing from app list.", LogLevel.Error);
                    apps.Remove(keys[i]);
                    continue;
                }

                Vector2 appPos = context.GetAppPos(i);
                e.SpriteBatch.Draw(app.icon, appPos, Color.White);

                Rectangle rect = new Rectangle((int)appPos.X, (int)appPos.Y, Config.IconWidth, Config.IconHeight);
                if (hover && rect.Contains(mousePos))
                {
                    ticksSinceMoved++;
                    if (ticksSinceMoved > Config.ToolTipDelayTicks)
                    {
                        appHover = app.name;
                    }
                }
            }
            if (appHover != null)
            {
                Utility.drawTextWithShadow(e.SpriteBatch, appHover, Game1.dialogueFont, new Vector2(mousePos.X, mousePos.Y) - Game1.dialogueFont.MeasureString(appHover), Color.White, 1f, -1f, -1, -1, 1f, 3);
            }
            lastPos = mousePos;
        }
예제 #19
0
        private static void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            if (ModEntry.callingNPC != null)
            {
                return;
            }

            if (!ModEntry.appRunning || !ModEntry.phoneOpen || ModEntry.runningApp != Helper.ModRegistry.ModID)
            {
                ModEntry.appRunning                     = false;
                ModEntry.phoneAppRunning                = false;
                Helper.Events.Display.RenderedWorld    -= Display_RenderedWorld;
                Helper.Events.Input.ButtonPressed      -= Input_ButtonPressed;
                Helper.Events.Input.MouseWheelScrolled -= Input_MouseWheelScrolled;
                return;
            }
            Vector2   screenPos  = PhoneUtils.GetScreenPosition();
            Vector2   screenSize = PhoneUtils.GetScreenSize();
            Rectangle headerRect = new Rectangle((int)screenPos.X, (int)screenPos.Y, (int)screenSize.X, Config.AppHeaderHeight);
            Point     mousePos   = Game1.getMousePosition();

            if (Helper.Input.IsSuppressed(SButton.MouseLeft))
            {
                int dy = mousePos.Y - lastMousePositionY;
                if (Math.Abs(dy) > 0 && ModEntry.screenRect.Contains(mousePos))
                {
                    dragging = true;
                }
                if (dragging)
                {
                    AddYOffset(dy);
                }
            }

            if (clicked && !Helper.Input.IsSuppressed(SButton.MouseLeft))
            {
                clicked = false;
                if (dragging)
                {
                    Monitor.Log($"was dragging");
                    dragging = false;
                }
                else
                {
                    if (headerRect.Contains(mousePos))
                    {
                        if (new Rectangle((int)screenPos.X + (int)screenSize.X - Config.AppHeaderHeight, (int)screenPos.Y, Config.AppHeaderHeight, Config.AppHeaderHeight).Contains(mousePos))
                        {
                            PhoneUtils.ToggleApp(false);
                        }
                    }
                    else
                    {
                        for (int i = 0; i < callableList.Count; i++)
                        {
                            Vector2   pos = GetNPCPos(i);
                            Rectangle r   = new Rectangle((int)pos.X, (int)pos.Y, Config.ContactWidth, Config.ContactHeight);
                            if (r.Contains(mousePos))
                            {
                                Monitor.Log($"calling {callableList[i].npc.Name}");
                                //PhoneUtils.PlayRingTone();
                                CallNPC(callableList[i].npc);
                            }
                        }
                    }
                }
            }

            lastMousePositionY = Game1.getMouseY();
            int startListY = (int)screenPos.Y + Config.AppHeaderHeight;

            e.SpriteBatch.Draw(ModEntry.phoneBookTexture, screenPos, Color.White);

            if (yOffset < 0)
            {
                e.SpriteBatch.Draw(ModEntry.upArrowTexture, ModEntry.upArrowPosition, Color.White);
            }
            if (yOffset > PhoneUtils.GetScreenSize().Y - Config.AppHeaderHeight - listHeight)
            {
                e.SpriteBatch.Draw(ModEntry.downArrowTexture, ModEntry.downArrowPosition, Color.White);
            }

            int screenBottom = (int)(screenPos.Y + screenSize.Y);

            for (int i = 0; i < callableList.Count; i++)
            {
                Vector2   npcPos = GetNPCPos(i);
                Rectangle r      = callableList[i].sourceRect;
                if (npcPos.Y < startListY - r.Height * 2 || npcPos.Y >= screenBottom)
                {
                    continue;
                }
                Rectangle sourceRect = r;
                int       cutTop     = 0;
                int       cutBottom  = 0;
                if (npcPos.Y < startListY)
                {
                    cutTop     = (int)Math.Round((startListY - (int)npcPos.Y) / 2f);
                    sourceRect = new Rectangle(r.X, r.Y + cutTop, r.Width, r.Height - cutTop);
                    npcPos     = new Vector2(npcPos.X, startListY);
                }
                else if (npcPos.Y > screenBottom - r.Height * 2)
                {
                    cutBottom  = (int)Math.Round((screenBottom - r.Height * 2 - (int)npcPos.Y) / 2f);
                    sourceRect = new Rectangle(r.X, r.Y, r.Width, r.Height + cutBottom);
                }
                int alpha = callableList[i].npc.CurrentDialogue.Any() && !callableList[i].npc.isSleeping ? 255 : Config.UncallableNPCAlpha;
                e.SpriteBatch.Draw(callableList[i].portrait, npcPos + new Vector2((Config.ContactWidth - 32) / 2f, 0), sourceRect, new Color(255, 255, 255, alpha), 0, Vector2.Zero, 2, SpriteEffects.None, 0.86f);
                if (Config.ShowNamesInPhoneBook && npcPos.Y < screenBottom - Config.ContactHeight - callableList[i].nameSize.Y * 0.4f + 6)
                {
                    e.SpriteBatch.DrawString(Game1.dialogueFont, callableList[i].name, GetNPCPos(i) + new Vector2(Config.ContactWidth / 2f - callableList[i].nameSize.X * 0.2f, Config.ContactHeight - 6), Color.Black, 0, Vector2.Zero, 0.4f, SpriteEffects.None, 0.86f);
                }
            }
            e.SpriteBatch.Draw(ModEntry.phoneBookHeaderTexture, headerRect, Color.White);
            string  headerText     = Helper.Translation.Get("phone-book");
            Vector2 headerTextSize = Game1.dialogueFont.MeasureString(headerText) * Config.HeaderTextScale;

            e.SpriteBatch.DrawString(Game1.dialogueFont, headerText, screenPos + new Vector2(screenSize.X / 2f - headerTextSize.X / 2f, Config.AppHeaderHeight / 2f - headerTextSize.Y / 2f), Config.PhoneBookHeaderTextColor, 0, Vector2.Zero, Config.HeaderTextScale, SpriteEffects.None, 0.86f);
            e.SpriteBatch.DrawString(Game1.dialogueFont, "x", screenPos + new Vector2(screenSize.X - Config.AppHeaderHeight / 2f - Game1.dialogueFont.MeasureString("x").X *Config.HeaderTextScale / 2f, Config.AppHeaderHeight / 2f - headerTextSize.Y / 2f), Config.PhoneBookHeaderTextColor, 0, Vector2.Zero, Config.HeaderTextScale, SpriteEffects.None, 0.86f);
        }
예제 #20
0
        private static void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            if (ModEntry.callingNPC != null)
            {
                return;
            }

            if (!ModEntry.appRunning || !ModEntry.phoneOpen || ModEntry.runningApp != Helper.ModRegistry.ModID)
            {
                ModEntry.appRunning = false;
                Helper.Events.Display.RenderedWorld -= Display_RenderedWorld;
                Helper.Events.Input.ButtonPressed   -= Input_ButtonPressed;
                return;
            }
            Vector2   screenPos  = PhoneUtils.GetScreenPosition();
            Vector2   screenSize = PhoneUtils.GetScreenSize();
            Rectangle headerRect = new Rectangle((int)screenPos.X, (int)screenPos.Y, (int)screenSize.X, Config.AppHeaderHeight);
            Rectangle footerRect = new Rectangle((int)screenPos.X, (int)screenPos.Y + (int)screenSize.Y - Config.AppHeaderHeight, (int)screenSize.X, Config.AppHeaderHeight);
            Point     mousePos   = Game1.getMousePosition();

            if (Helper.Input.IsSuppressed(SButton.MouseLeft))
            {
                int dy = mousePos.Y - lastMousePositionY;
                if (Math.Abs(dy) > 0 && ModEntry.screenRect.Contains(mousePos) && !headerRect.Contains(mousePos) && !footerRect.Contains(mousePos))
                {
                    dragging = true;
                }
                if (dragging)
                {
                    float listHeight;
                    if (whichTab == 0)
                    {
                        listHeight = skinListHeight;
                    }
                    else if (whichTab == 1)
                    {
                        listHeight = backListHeight;
                    }
                    else
                    {
                        listHeight = ringListHeight;
                    }
                    yOffset = (int)Math.Max(Math.Min(0, yOffset + dy), -1 * Math.Max(0, listHeight - screenSize.Y));
                }
            }

            if (clicked && !Helper.Input.IsSuppressed(SButton.MouseLeft))
            {
                clicked = false;
                Monitor.Log($"unclicked");
                if (dragging)
                {
                    Monitor.Log($"was dragging");
                    dragging = false;
                }
                else
                {
                    if (headerRect.Contains(mousePos))
                    {
                        if (new Rectangle((int)screenPos.X + (int)screenSize.X - Config.AppHeaderHeight, (int)screenPos.Y, Config.AppHeaderHeight, Config.AppHeaderHeight).Contains(mousePos))
                        {
                            PhoneUtils.ToggleApp(false);
                        }
                    }
                    else if (footerRect.Contains(mousePos))
                    {
                        int newTab = (int)((mousePos.X - screenPos.X) / (screenSize.X / 3));
                        if (whichTab != newTab)
                        {
                            whichTab = newTab;
                            yOffset  = 0;
                            int listcount = whichTab == 0 ? skinList.Count : (whichTab == 1 ? backgroundList.Count : ringList.Count);
                            Monitor.Log($"switching to tab {whichTab}: {listcount} items");
                        }
                    }
                    else
                    {
                        if (whichTab == 0)
                        {
                            for (int i = 0; i < skinList.Count; i++)
                            {
                                Vector2   pos = GetItemPos(i);
                                Rectangle r   = new Rectangle((int)pos.X, (int)pos.Y, Config.ThemeItemWidth, Config.ThemeItemHeight);
                                if (r.Contains(mousePos))
                                {
                                    Monitor.Log($"switching to {skinList[i]}");
                                    SetSkin(skinList[i]);
                                }
                            }
                        }
                        else if (whichTab == 1)
                        {
                            for (int i = 0; i < backgroundList.Count; i++)
                            {
                                Vector2   pos = GetItemPos(i);
                                Rectangle r   = new Rectangle((int)pos.X, (int)pos.Y, Config.ThemeItemWidth, Config.ThemeItemHeight);
                                if (r.Contains(mousePos))
                                {
                                    Monitor.Log($"switching to {backgroundList[i]}");
                                    SetBackground(backgroundList[i]);
                                }
                            }
                        }
                        else if (whichTab == 2)
                        {
                            for (int i = 0; i < ringList.Count; i++)
                            {
                                Vector2   pos = GetItemPos(i);
                                Rectangle r   = new Rectangle((int)pos.X, (int)pos.Y, ModEntry.phoneWidth, Config.RingListItemHeight);
                                if (r.Contains(mousePos))
                                {
                                    Monitor.Log($"switching to {ringList[i]}");
                                    SetRing(ringList[i]);
                                }
                            }
                        }
                    }
                }
            }

            lastMousePositionY = Game1.getMouseY();
            int startListY = (int)screenPos.Y + Config.AppHeaderHeight;

            if (whichTab == 2)
            {
                e.SpriteBatch.Draw(ModEntry.ringListBackgroundTexture, ModEntry.screenRect, Color.White);
            }
            else
            {
                e.SpriteBatch.Draw(ModEntry.backgroundTexture, ModEntry.phoneRect, Color.White);
            }

            if (yOffset < 0)
            {
                e.SpriteBatch.Draw(ModEntry.upArrowTexture, ModEntry.upArrowPosition, Color.White);
            }
            if (yOffset > PhoneUtils.GetScreenSize().Y - Config.AppHeaderHeight - skinListHeight)
            {
                e.SpriteBatch.Draw(ModEntry.downArrowTexture, ModEntry.downArrowPosition, Color.White);
            }

            int screenBottom = (int)(screenPos.Y + screenSize.Y);

            int count = whichTab == 0 ? skinList.Count : (whichTab == 1 ? backgroundList.Count : ringList.Count);


            for (int i = 0; i < count; i++)
            {
                Vector2 itemPos = GetItemPos(i);
                if (whichTab < 2)
                {
                    Rectangle r          = new Rectangle(0, 0, Config.PhoneWidth, Config.PhoneHeight);
                    Rectangle sourceRect = r;
                    Rectangle destRect;
                    destRect = new Rectangle((int)itemPos.X, (int)itemPos.Y, Config.ThemeItemWidth, Config.ThemeItemHeight);
                    float yScale = Config.ThemeItemHeight / (float)Config.PhoneHeight;
                    if (itemPos.Y < startListY - r.Height * yScale || itemPos.Y >= screenBottom)
                    {
                        continue;
                    }
                    int cutTop    = 0;
                    int cutBottom = 0;
                    if (itemPos.Y < startListY)
                    {
                        cutTop           = (int)Math.Ceiling((startListY - itemPos.Y) / yScale);
                        sourceRect       = new Rectangle(r.X, (int)(r.Y + cutTop), r.Width, (int)(r.Height - cutTop));
                        destRect.Y       = startListY;
                        destRect.Height -= (int)(cutTop * yScale);
                        itemPos          = new Vector2(itemPos.X, startListY);
                    }
                    else if (itemPos.Y > screenBottom - r.Height * yScale - Config.AppHeaderHeight)
                    {
                        cutBottom        = (int)Math.Ceiling((screenBottom - Config.AppHeaderHeight - r.Height * yScale - itemPos.Y) / yScale);
                        destRect.Height += (int)(cutBottom * yScale);
                        sourceRect       = new Rectangle(r.X, r.Y, r.Width, r.Height + cutBottom);
                    }
                    Texture2D texture = whichTab == 0 ? skinDict[skinList[i]][0] : backgroundDict[backgroundList[i]][0];
                    //Monitor.Log($"drawing texture {i} {texture.Width}x{texture.Height} {destRect} {ModEntry.screenRect}");
                    e.SpriteBatch.Draw(texture, destRect, sourceRect, Color.White);
                }
                else
                {
                    if (itemPos.Y < screenPos.Y || itemPos.Y >= screenBottom - Config.AppHeaderHeight)
                    {
                        continue;
                    }
                    if (ringList[i] == Config.PhoneRingTone)
                    {
                        e.SpriteBatch.Draw(ModEntry.ringListHighlightTexture, new Rectangle((int)(itemPos.X), (int)itemPos.Y, (int)(screenSize.X), Config.RingListItemHeight), Color.White);
                    }

                    string itemName = ringList[i];
                    if (itemName.Contains(":"))
                    {
                        itemName = itemName.Split(':')[1];
                    }
                    e.SpriteBatch.DrawString(Game1.dialogueFont, itemName, itemPos, Config.RingListItemColor, 0, Vector2.Zero, Config.RingListItemScale, SpriteEffects.None, 0.86f);
                }
            }
            e.SpriteBatch.Draw(ModEntry.themesHeaderTexture, headerRect, Color.White);
            e.SpriteBatch.Draw(ModEntry.themesHeaderTexture, footerRect, Color.White);
            e.SpriteBatch.Draw(ModEntry.themesHighlightTexture, new Rectangle((int)(screenPos.X + (screenSize.X / 3f) * whichTab), screenBottom - Config.AppHeaderHeight, (int)(screenSize.X / 3f), Config.AppHeaderHeight), Color.White);
            string  headerText     = Helper.Translation.Get("themes");
            string  skinsText      = Helper.Translation.Get("skins");
            string  backsText      = Helper.Translation.Get("backs");
            string  ringsText      = Helper.Translation.Get("rings");
            Vector2 headerTextSize = Game1.dialogueFont.MeasureString(headerText) * Config.HeaderTextScale;
            Vector2 skinsTextSize  = Game1.dialogueFont.MeasureString(skinsText) * Config.TabTextScale;
            Vector2 backsTextSize  = Game1.dialogueFont.MeasureString(backsText) * Config.TabTextScale;
            Vector2 ringsTextSize  = Game1.dialogueFont.MeasureString(ringsText) * Config.TabTextScale;

            e.SpriteBatch.DrawString(Game1.dialogueFont, headerText, screenPos + new Vector2(screenSize.X / 2f - headerTextSize.X / 2f, Config.AppHeaderHeight / 2f - headerTextSize.Y / 2f), Config.PhoneBookHeaderTextColor, 0, Vector2.Zero, Config.HeaderTextScale, SpriteEffects.None, 0.86f);
            e.SpriteBatch.DrawString(Game1.dialogueFont, "x", screenPos + new Vector2(screenSize.X - Config.AppHeaderHeight / 2f - Game1.dialogueFont.MeasureString("x").X *Config.HeaderTextScale / 2f, Config.AppHeaderHeight / 2f - headerTextSize.Y / 2f), Config.PhoneBookHeaderTextColor, 0, Vector2.Zero, Config.HeaderTextScale, SpriteEffects.None, 0.86f);
            e.SpriteBatch.DrawString(Game1.dialogueFont, skinsText, screenPos + new Vector2(screenSize.X / 6f - skinsTextSize.X / 2f, screenSize.Y - Config.AppHeaderHeight / 2f - headerTextSize.Y / 2f), whichTab == 0 ? Config.ThemesHeaderHighlightedTextColor : Config.ThemesHeaderTextColor, 0, Vector2.Zero, Config.TabTextScale, SpriteEffects.None, 0.86f);
            e.SpriteBatch.DrawString(Game1.dialogueFont, backsText, screenPos + new Vector2(screenSize.X / 2f - backsTextSize.X / 2f, screenSize.Y - Config.AppHeaderHeight / 2f - headerTextSize.Y / 2f), whichTab == 1 ? Config.ThemesHeaderHighlightedTextColor : Config.ThemesHeaderTextColor, 0, Vector2.Zero, Config.TabTextScale, SpriteEffects.None, 0.86f);
            e.SpriteBatch.DrawString(Game1.dialogueFont, ringsText, screenPos + new Vector2(screenSize.X * 5f / 6f - ringsTextSize.X / 2f, screenSize.Y - Config.AppHeaderHeight / 2f - headerTextSize.Y / 2f), whichTab == 2 ? Config.ThemesHeaderHighlightedTextColor : Config.ThemesHeaderTextColor, 0, Vector2.Zero, Config.TabTextScale, SpriteEffects.None, 0.86f);
        }
예제 #21
0
        public static void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            Point mousePos     = Game1.getMousePosition();
            Point lastMousePos = ModEntry.lastMousePosition;

            ModEntry.lastMousePosition = mousePos;

            if (!ModEntry.phoneOpen)
            {
                ModEntry.appRunning = false;
                ModEntry.runningApp = null;

                if (Config.ShowPhoneIcon && Game1.displayHUD && !Game1.eventUp && Game1.currentBillboard == 0 && Game1.gameMode == 3 && !Game1.freezeControls && !Game1.panMode && !Game1.HostPaused && !Game1.game1.takingMapScreenshot)
                {
                    if (ModEntry.clickingPhoneIcon)
                    {
                        if (Helper.Input.IsSuppressed(SButton.MouseLeft) && lastMousePos != mousePos)
                        {
                            ModEntry.draggingPhoneIcon = true;
                            Config.PhoneIconOffsetX   += mousePos.X - lastMousePos.X;
                            Config.PhoneIconOffsetY   += mousePos.Y - lastMousePos.Y;
                            ModEntry.phoneIconPosition = PhoneUtils.GetPhoneIconPosition();
                        }
                        else if (!Helper.Input.IsSuppressed(SButton.MouseLeft))
                        {
                            if (!ModEntry.draggingPhoneIcon)
                            {
                                PhoneUtils.TogglePhone(true);
                            }
                            else
                            {
                                Helper.WriteConfig(Config);
                            }
                            ModEntry.clickingPhoneIcon = false;
                            ModEntry.draggingPhoneIcon = false;
                        }
                    }
                    e.SpriteBatch.Draw(ModEntry.iconTexture, ModEntry.phoneIconPosition, Color.White);
                }

                return;
            }
            else
            {
                ModEntry.clickingPhoneIcon = false;
                ModEntry.draggingPhoneIcon = false;
            }

            if (Game1.game1.takingMapScreenshot)
            {
                return;
            }

            if (ModEntry.draggingPhone)
            {
                if (Helper.Input.IsSuppressed(SButton.MouseLeft))
                {
                    if (mousePos != lastMousePos)
                    {
                        int x = mousePos.X - lastMousePos.X;
                        int y = mousePos.Y - lastMousePos.Y;
                        if (ModEntry.phoneRotated)
                        {
                            Config.PhoneRotatedOffsetX += x;
                            Config.PhoneRotatedOffsetY += y;
                        }
                        else
                        {
                            Config.PhoneOffsetX += x;
                            Config.PhoneOffsetY += y;
                        }
                        PhoneUtils.RefreshPhoneLayout();
                    }
                }
                else
                {
                    ModEntry.context.Helper.WriteConfig(Config);
                    ModEntry.draggingPhone = false;
                    Monitor.Log($"released dragging phone");
                }
            }
            else if (Helper.Input.IsSuppressed(SButton.MouseLeft) && !ModEntry.movingAppIcon)
            {
                int dy = mousePos.Y - lastMousePos.Y;
                if (Math.Abs(dy) > 0 && ModEntry.screenRect.Contains(mousePos))
                {
                    ModEntry.clickingApp   = -1;
                    ModEntry.draggingIcons = true;
                }
                if (ModEntry.draggingIcons)
                {
                    ModEntry.yOffset = (int)Math.Max(Math.Min(0, ModEntry.yOffset + dy), -1 * Math.Max(0, ModEntry.listHeight - PhoneUtils.GetScreenSize().Y));
                }
            }

            e.SpriteBatch.Draw(ModEntry.phoneRotated ? ModEntry.backgroundRotatedTexture : ModEntry.backgroundTexture, ModEntry.phoneRect, Color.White);
            e.SpriteBatch.Draw(ModEntry.phoneRotated ? ModEntry.phoneRotatedTexture : ModEntry.phoneTexture, ModEntry.phoneRect, Color.White);

            Vector2 screenPos  = PhoneUtils.GetScreenPosition();
            Vector2 screenSize = PhoneUtils.GetScreenSize();

            if (ModEntry.callingNPC != null)
            {
                Rectangle destRect;
                Rectangle portraitSource = Game1.getSourceRectForStandardTileSheet(ModEntry.callingNPC.Portrait, 0, 64, 64);
                float     scale;
                if ((float)portraitSource.Height * screenSize.X / (float)portraitSource.Width > screenSize.Y - Config.AppHeaderHeight)
                {
                    scale    = (screenSize.Y - Config.AppHeaderHeight) / (float)portraitSource.Height;
                    destRect = new Rectangle((int)(screenPos.X + screenSize.X / 2f - portraitSource.Width * scale / 2f), (int)screenPos.Y, (int)(portraitSource.Width * scale), (int)screenSize.Y - Config.AppHeaderHeight);
                }
                else
                {
                    scale = screenSize.X / (float)portraitSource.Width;
                    //Monitor.Log($"{screenSize} {portraitSource.Width},{portraitSource.Height} {scale}");
                    destRect = new Rectangle((int)(screenPos.X), (int)(screenPos.Y + (screenSize.Y - Config.AppHeaderHeight) / 2f - portraitSource.Height * scale / 2f), (int)screenSize.X, (int)(portraitSource.Height * scale));
                }
                e.SpriteBatch.Draw(ModEntry.callingNPC.Portrait, destRect, new Rectangle?(portraitSource), Color.White);
                SpriteText.drawStringHorizontallyCenteredAt(e.SpriteBatch, ModEntry.callingNPC.getName(), destRect.X + destRect.Width / 2, destRect.Bottom + 16, 999999, -1, 999999, 1f, 0.88f, false, -1, 99999);

                if (!ModEntry.inCall)
                {
                    Rectangle answerRect  = new Rectangle((int)(screenPos.X), ModEntry.screenRect.Bottom - Config.AppHeaderHeight, (int)(screenSize.X / 2f), Config.AppHeaderHeight);
                    Rectangle declineRect = new Rectangle((int)(screenPos.X + screenSize.X / 2f), ModEntry.screenRect.Bottom - Config.AppHeaderHeight, (int)(screenSize.X / 2f), Config.AppHeaderHeight);
                    e.SpriteBatch.Draw(ModEntry.answerTexture, answerRect, Color.White);
                    e.SpriteBatch.Draw(ModEntry.declineTexture, declineRect, Color.White);
                    float   textScale = Config.CallTextScale;
                    string  ans       = Helper.Translation.Get("answer");
                    Vector2 ansSize   = Game1.dialogueFont.MeasureString(ans) * textScale;
                    string  dec       = Helper.Translation.Get("decline");
                    Vector2 decSize   = Game1.dialogueFont.MeasureString(dec) * textScale;
                    e.SpriteBatch.DrawString(Game1.dialogueFont, ans, new Vector2(answerRect.X + answerRect.Width / 2f - ansSize.X / 2f, answerRect.Top + answerRect.Height / 2f - ansSize.Y / 2f), Config.CallTextColor, 0f, Vector2.Zero, textScale, SpriteEffects.None, 1f);
                    e.SpriteBatch.DrawString(Game1.dialogueFont, dec, new Vector2(declineRect.X + declineRect.Width / 2f - decSize.X / 2f, declineRect.Top + declineRect.Height / 2f - decSize.Y / 2f), Config.CallTextColor, 0f, Vector2.Zero, textScale, SpriteEffects.None, 1f);
                    if (ModEntry.clicking && !Helper.Input.IsSuppressed(SButton.MouseLeft))
                    {
                        if (answerRect.Contains(mousePos))
                        {
                            MobilePhoneApp.CallNPC(ModEntry.callingNPC);
                            ModEntry.currentCallRings = 0;
                        }
                        else if (declineRect.Contains(mousePos))
                        {
                            ModEntry.currentCallRings = 0;
                            ModEntry.callingNPC       = null;
                        }
                    }
                }
                else
                {
                    Rectangle endRect = new Rectangle((int)(screenPos.X + screenSize.X / 4), ModEntry.screenRect.Bottom - Config.AppHeaderHeight, (int)(screenSize.X / 2), Config.AppHeaderHeight);
                    e.SpriteBatch.Draw(ModEntry.declineTexture, endRect, Color.White);
                    float   textScale = Config.CallTextScale;
                    string  ends      = Helper.Translation.Get("end-call");
                    Vector2 endsSize  = Game1.dialogueFont.MeasureString(ends) * textScale;
                    e.SpriteBatch.DrawString(Game1.dialogueFont, ends, new Vector2(endRect.X + endRect.Width / 2f - endsSize.X / 2f, endRect.Top + endRect.Height / 2f - endsSize.Y / 2f), Config.CallTextColor, 0f, Vector2.Zero, textScale, SpriteEffects.None, 1f);
                    if (ModEntry.clicking && !Helper.Input.IsSuppressed(SButton.MouseLeft))
                    {
                        if (endRect.Contains(mousePos))
                        {
                            MobilePhoneCall.EndCall();
                            if (Game1.activeClickableMenu is DialogueBox)
                            {
                                Game1.activeClickableMenu = null;
                            }
                        }
                    }
                }
                if ((ModEntry.clicking || ModEntry.clickingPhoneIcon) && !Helper.Input.IsSuppressed(SButton.MouseLeft))
                {
                    ModEntry.clickingApp         = -1;
                    ModEntry.switchingApp        = -1;
                    ModEntry.movingAppIconOffset = new Point(0, 0);
                    ModEntry.clickingTicks       = 0;
                    ModEntry.clicking            = false;
                    ModEntry.movingAppIcon       = false;
                    ModEntry.clickingPhoneIcon   = false;
                    ModEntry.draggingPhone       = false;
                    ModEntry.draggingIcons       = false;
                }

                return;
            }

            if (ModEntry.appRunning)
            {
                return;
            }
            if (ModEntry.runningApp == Helper.ModRegistry.ModID && Game1.activeClickableMenu == null)
            {
                MobilePhoneApp.OpenPhoneBook();
                return;
            }

            List <string> keys = new List <string>(ModEntry.appOrder);

            if ((ModEntry.clicking || ModEntry.clickingPhoneIcon) && !Helper.Input.IsSuppressed(SButton.MouseLeft))
            {
                Monitor.Log($"released click");
                if (ModEntry.movingAppIcon && ModEntry.switchingApp != -1)
                {
                    Monitor.Log($"switching app: {ModEntry.switchingApp} clicking app {ModEntry.clickingApp}");
                    Game1.playSound("stoneStep");
                    ModEntry.appOrder[ModEntry.clickingApp]  = keys[ModEntry.switchingApp];
                    ModEntry.appOrder[ModEntry.switchingApp] = keys[ModEntry.clickingApp];
                    keys           = new List <string>(ModEntry.appOrder);
                    Config.AppList = keys.ToArray();
                    Helper.WriteConfig(Config);
                }
                else if (ModEntry.draggingIcons)
                {
                    ModEntry.draggingIcons = false;
                }
                else if (!ModEntry.movingAppIcon)
                {
                    for (int i = 0; i < keys.Count; i++)
                    {
                        Vector2   pos = PhoneUtils.GetAppPos(i);
                        Rectangle r   = new Rectangle((int)pos.X, (int)pos.Y, Config.IconWidth, Config.IconHeight);
                        if (r.Contains(mousePos))
                        {
                            if (ModEntry.apps[keys[i]].keyPress != null)
                            {
                                Monitor.Log($"pressing key {ModEntry.apps[keys[i]].keyPress}");
                                PhoneInput.PressKey(ModEntry.apps[keys[i]]);
                            }
                            else
                            {
                                Monitor.Log($"starting app {ModEntry.apps[keys[i]].name}");
                                ModEntry.apps[keys[i]].action.Invoke();
                            }
                        }
                    }
                }
                ModEntry.clickingApp         = -1;
                ModEntry.switchingApp        = -1;
                ModEntry.movingAppIconOffset = new Point(0, 0);
                ModEntry.clickingTicks       = 0;
                ModEntry.clicking            = false;
                ModEntry.movingAppIcon       = false;
                ModEntry.clickingPhoneIcon   = false;
                ModEntry.draggingPhone       = false;
                ModEntry.draggingIcons       = false;
            }
            else if (ModEntry.clicking && ModEntry.clickingApp != -1 && !ModEntry.movingAppIcon)
            {
                if (lastMousePos == mousePos)
                {
                    if (ModEntry.clickingTicks > Config.TicksToMoveAppIcon)
                    {
                        Game1.playSound("pickUpItem");
                        ModEntry.movingAppIconOffset = new Point(5, 5);
                        ModEntry.movingAppIcon       = true;
                    }
                    else
                    {
                        ModEntry.clickingTicks++;
                    }
                }
                else
                {
                    ModEntry.clickingTicks = 0;
                    ModEntry.clickingApp   = -1;
                }
            }
            else if (ModEntry.movingAppIcon)
            {
                ModEntry.movingAppIconOffset = new Point(ModEntry.movingAppIconOffset.X + mousePos.X - lastMousePos.X, ModEntry.movingAppIconOffset.Y + mousePos.Y - lastMousePos.Y);
                Vector2 currentPos = PhoneUtils.GetAppPos(ModEntry.clickingApp);
                if (ModEntry.screenRect.Contains(Utility.Vector2ToPoint(currentPos)))
                {
                    bool alreadySwitched = false;
                    if (ModEntry.switchingApp != -1)
                    {
                        Vector2 pos = PhoneUtils.GetAppPos(ModEntry.switchingApp, true);
                        if (Vector2.Distance(currentPos, pos) < (Config.IconWidth + Config.IconHeight) / 4f)
                        {
                            alreadySwitched = true;
                        }
                    }
                    if (!alreadySwitched)
                    {
                        for (int i = 0; i < keys.Count; i++)
                        {
                            Vector2 pos = PhoneUtils.GetAppPos(i);
                            if (i != ModEntry.clickingApp && Vector2.Distance(currentPos, pos) < (Config.IconWidth + Config.IconHeight) / 4f)
                            {
                                ModEntry.switchingApp = i;
                                Monitor.Log($"new switching app: {ModEntry.switchingApp} clicking app {ModEntry.clickingApp}");
                                break;
                            }
                            else
                            {
                                ModEntry.switchingApp = -1;
                            }
                        }
                    }
                }
            }


            string appHover = null;
            bool   hover    = false;

            if (mousePos == lastMousePos && !Helper.Input.IsSuppressed(SButton.MouseLeft))
            {
                hover = true;
            }
            else
            {
                ModEntry.ticksSinceMoved = 0;
            }

            int screenBottom = (int)(screenPos.Y + screenSize.Y);

            for (int i = keys.Count - 1; i >= 0; i--)
            {
                MobileApp app = ModEntry.apps[keys[i]];

                Vector2   appPos     = PhoneUtils.GetAppPos(i);
                Rectangle r          = new Rectangle(0, 0, Config.IconWidth, Config.IconHeight);
                Rectangle sourceRect = r;
                if (!ModEntry.movingAppIcon || i != ModEntry.clickingApp)
                {
                    if (appPos.Y < screenPos.Y - r.Height * 2 || appPos.Y >= screenBottom)
                    {
                        continue;
                    }
                    if (appPos.Y < screenPos.Y)
                    {
                        int cutTop = (int)screenPos.Y - (int)appPos.Y;
                        sourceRect = new Rectangle(r.X, r.Y + cutTop, r.Width, r.Height - cutTop);
                        appPos     = new Vector2(appPos.X, screenPos.Y);
                    }
                    else if (appPos.Y > screenBottom - r.Height)
                    {
                        int cutBottom = screenBottom - r.Height - (int)appPos.Y;
                        sourceRect = new Rectangle(r.X, r.Y, r.Width, r.Height + cutBottom);
                    }
                }

                e.SpriteBatch.Draw(app.icon, new Rectangle((int)appPos.X, (int)appPos.Y, sourceRect.Width, sourceRect.Height), sourceRect, Color.White, 0, Vector2.Zero, SpriteEffects.None, i == ModEntry.clickingApp && ModEntry.movingAppIcon ? 1f : 0.5f);

                Rectangle rect = new Rectangle((int)appPos.X, (int)appPos.Y, Config.IconWidth, sourceRect.Height);
                if (hover && !Helper.Input.IsSuppressed(SButton.MouseLeft) && rect.Contains(mousePos))
                {
                    ModEntry.ticksSinceMoved++;
                    if (ModEntry.ticksSinceMoved > Config.ToolTipDelayTicks)
                    {
                        appHover = app.name;
                    }
                }
            }
            if (appHover != null)
            {
                e.SpriteBatch.DrawString(Game1.dialogueFont, appHover, new Vector2(mousePos.X, mousePos.Y) - Game1.dialogueFont.MeasureString(appHover) + new Vector2(-2, 2), Color.Black);
                e.SpriteBatch.DrawString(Game1.dialogueFont, appHover, new Vector2(mousePos.X, mousePos.Y) - Game1.dialogueFont.MeasureString(appHover), Color.White);
            }
        }
예제 #22
0
        private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            if (Game1.activeClickableMenu == null && PlacedAugmentorsManager.Instance != null)
            {
                GameLocation CurrentLocation = Game1.player.currentLocation;

                bool IsHoveringPlacedObject = CurrentLocation.Objects.TryGetValue(HoveredTile, out Object HoveredObject);
                if (IsHoveringPlacedObject)
                {
                    Dictionary <AugmentorType, int> AttachedAugmentors = PlacedAugmentorsManager.Instance.GetAugmentorQuantities(CurrentLocation.NameOrUniqueName, HoveredTile);
                    bool HasAttachedAugmentors = AttachedAugmentors.Any(x => x.Value > 0);
                    if (MachineInfo.TryGetMachineInfo(HoveredObject, out MachineInfo MI))
                    {
                        SpriteFont DefaultFont = Game1.dialogueFont;

                        //  Draw a tooltip showing what effects the held item will have when attached to this machine
                        if (Game1.player.CurrentItem is Augmentor HeldAugmentor && HeldAugmentor.IsAugmentable(HoveredObject))
                        {
                            AttachedAugmentors.TryGetValue(HeldAugmentor.AugmentorType, out int CurrentAttachedQuantity);

                            double CurrentEffect = CurrentAttachedQuantity <= 0 ?
                                                   Augmentor.GetDefaultEffect(HeldAugmentor.AugmentorType) : Augmentor.ComputeEffect(HeldAugmentor.AugmentorType, CurrentAttachedQuantity, MI.RequiresInput);
                            double NewEffectSingle = Augmentor.ComputeEffect(HeldAugmentor.AugmentorType, CurrentAttachedQuantity + 1, MI.RequiresInput);
                            double NewEffectAll    = Augmentor.ComputeEffect(HeldAugmentor.AugmentorType, CurrentAttachedQuantity + HeldAugmentor.Stack, MI.RequiresInput);

                            //  Example of desired tooltip:
                            //        -------------------------------------------
                            //        |          [Icon] Time to process:        |
                            //        |-----------------------------------------|
                            //        |  Current Effect: 95.5%                  |
                            //        |      New Effect: 92.2% (1) / 81.1% (4)  |
                            //        -------------------------------------------

                            int   Padding         = 28;
                            int   MarginAfterIcon = 10;
                            float LabelTextScale  = 0.75f;
                            float ValueTextScale  = 1.0f;

                            //  Compute sizes of each row so we know how big the tooltip is, and can horizontally center the header and other rows

                            //  Compute size of header
                            int HeaderHorizontalPadding = 4;
                            Augmentor.TryGetIconDetails(HeldAugmentor.AugmentorType, out Texture2D IconTexture, out Rectangle IconSourcePosition, out float IconScale, out SpriteEffects IconEffects);
                            Vector2 IconSize        = new Vector2(IconSourcePosition.Width * IconScale, IconSourcePosition.Height * IconScale);
                            string  HeaderText      = string.Format("{0}:", HeldAugmentor.GetEffectDescription());
                            Vector2 HeaderTextSize  = DefaultFont.MeasureString(HeaderText) * LabelTextScale;
                            float   HeaderRowWidth  = IconSize.X + MarginAfterIcon + HeaderTextSize.X + HeaderHorizontalPadding * 2;
                            float   HeaderRowHeight = Math.Max(IconSize.Y, HeaderTextSize.Y);

                            //  Compute size of horizontal separator
                            int HorizontalSeparatorHeight = 6;
                            int HorizontalSeparatorMargin = 8;

                            //  Compute size of the labels before the effect values
                            int     MarginAfterLabel       = 8;
                            string  CurrentEffectLabel     = string.Format("{0}:", Translate("CurrentEffectLabel"));
                            Vector2 CurrentEffectLabelSize = DefaultFont.MeasureString(CurrentEffectLabel) * LabelTextScale;
                            string  NewEffectLabel         = string.Format("{0}:", Translate("NewEffectLabel"));
                            Vector2 NewEffectLabelSize     = DefaultFont.MeasureString(NewEffectLabel) * LabelTextScale;
                            float   EffectLabelWidth       = Math.Max(CurrentEffectLabelSize.X, NewEffectLabelSize.X);
                            Vector2 EffectLabelSize        = new Vector2(EffectLabelWidth, CurrentEffectLabelSize.Y + NewEffectLabelSize.Y);

                            //  Compute size of the effect values
                            string  CurrentEffectValue     = string.Format("{0}% ({1})", (CurrentEffect * 100.0).ToString("0.##"), CurrentAttachedQuantity);
                            Vector2 CurrentEffectValueSize = DrawHelpers.MeasureStringWithSpecialNumbers(CurrentEffectValue, ValueTextScale, 0.0f);
                            string  NewEffectValue;
                            if (HeldAugmentor.Stack > 1)
                            {
                                NewEffectValue = string.Format("{0}% ({1}) / {2}% ({3})",
                                                               (NewEffectSingle * 100.0).ToString("0.##"), (CurrentAttachedQuantity + 1), (NewEffectAll * 100.0).ToString("0.##"), (CurrentAttachedQuantity + HeldAugmentor.Stack));
                            }
                            else
                            {
                                NewEffectValue = string.Format("{0}% ({1})", (NewEffectSingle * 100.0).ToString("0.##"), (CurrentAttachedQuantity + 1));
                            }
                            Vector2 NewEffectValueSize = DrawHelpers.MeasureStringWithSpecialNumbers(NewEffectValue, ValueTextScale, 0.0f);

                            Vector2 EffectContentSize = new Vector2(EffectLabelWidth + MarginAfterLabel + Math.Max(CurrentEffectValueSize.X, NewEffectValueSize.X),
                                                                    Math.Max(CurrentEffectLabelSize.Y, CurrentEffectValueSize.Y) + Math.Max(NewEffectLabelSize.Y, NewEffectValueSize.Y));

                            //  Compute total size of tooltip, draw the background
                            Vector2 ToolTipSize    = new Vector2(Padding * 2 + Math.Max(HeaderRowWidth, EffectContentSize.X), Padding + HeaderRowHeight + HorizontalSeparatorMargin + HorizontalSeparatorHeight + HorizontalSeparatorMargin + EffectContentSize.Y + Padding);
                            Point   ToolTipTopleft = DrawHelpers.GetTopleftPosition(new Point((int)ToolTipSize.X, (int)ToolTipSize.Y), MouseScreenPosition, 100);
                            DrawHelpers.DrawBox(e.SpriteBatch, new Rectangle(ToolTipTopleft.X, ToolTipTopleft.Y, (int)ToolTipSize.X, (int)ToolTipSize.Y));
                            float CurrentY = ToolTipTopleft.Y + Padding;

                            //  Draw the header
                            float   HeaderStartX = ToolTipTopleft.X + (ToolTipSize.X - HeaderRowWidth) / 2.0f;
                            Vector2 IconPosition = new Vector2(HeaderStartX, CurrentY + (HeaderRowHeight - IconSize.Y) / 2.0f);
                            e.SpriteBatch.Draw(IconTexture, IconPosition, IconSourcePosition, Color.White, 0f, Vector2.Zero, IconScale, IconEffects, 1f);
                            Vector2 HeaderTextPosition = new Vector2(HeaderStartX + IconSize.X + MarginAfterIcon, CurrentY + (HeaderRowHeight - HeaderTextSize.Y) / 2.0f);
                            e.SpriteBatch.DrawString(DefaultFont, HeaderText, HeaderTextPosition, Color.Black, 0.0f, Vector2.Zero, LabelTextScale, SpriteEffects.None, 1.0f);
                            CurrentY += HeaderRowHeight + HorizontalSeparatorMargin;

                            //  Draw the horizontal separator
                            DrawHelpers.DrawHorizontalSeparator(e.SpriteBatch, ToolTipTopleft.X + Padding, (int)CurrentY, (int)(ToolTipSize.X - 2 * Padding), HorizontalSeparatorHeight);
                            CurrentY += HorizontalSeparatorHeight + HorizontalSeparatorMargin;

                            //  Draw the current effect
                            Vector2 CurrentEffectLabelPosition = new Vector2(ToolTipTopleft.X + Padding + (EffectLabelWidth - CurrentEffectLabelSize.X), CurrentY);
                            Vector2 CurrentEffectValuePosition = new Vector2(ToolTipTopleft.X + Padding + EffectLabelWidth + MarginAfterLabel, CurrentY);
                            e.SpriteBatch.DrawString(DefaultFont, CurrentEffectLabel, CurrentEffectLabelPosition, Color.Black, 0.0f, Vector2.Zero, LabelTextScale, SpriteEffects.None, 1.0f);
                            DrawHelpers.DrawStringWithSpecialNumbers(e.SpriteBatch, CurrentEffectValuePosition, CurrentEffectValue, ValueTextScale, Color.White);
                            CurrentY += Math.Max(CurrentEffectLabelSize.Y, CurrentEffectValueSize.Y);

                            //  Draw the new effect
                            Vector2 NewEffectLabelPosition = new Vector2(ToolTipTopleft.X + Padding + (EffectLabelWidth - NewEffectLabelSize.X), CurrentY);
                            Vector2 NewEffectValuePosition = new Vector2(ToolTipTopleft.X + Padding + EffectLabelWidth + MarginAfterLabel, CurrentY);
                            e.SpriteBatch.DrawString(DefaultFont, NewEffectLabel, NewEffectLabelPosition, Color.Black, 0.0f, Vector2.Zero, LabelTextScale, SpriteEffects.None, 1.0f);
                            DrawHelpers.DrawStringWithSpecialNumbers(e.SpriteBatch, NewEffectValuePosition, NewEffectValue, ValueTextScale, Color.White);
                        }
                        //  Draw a tooltip showing what effects are currently applied to this machine
                        else if (HasAttachedAugmentors)
                        {
                            int Padding         = 28;
                            int MarginAfterIcon = 10;

                            //  Compute the size of each icon
                            Dictionary <AugmentorType, Vector2> IconSizes = new Dictionary <AugmentorType, Vector2>();
                            foreach (KeyValuePair <AugmentorType, int> KVP in AttachedAugmentors.Where(x => x.Value > 0))
                            {
                                Augmentor.TryGetIconDetails(KVP.Key, out Texture2D IconTexture, out Rectangle IconSourcePosition, out float IconScale, out SpriteEffects IconEffects);
                                Vector2 IconSize = new Vector2(IconSourcePosition.Width * IconScale, IconSourcePosition.Height * IconScale);
                                IconSizes.Add(KVP.Key, IconSize);
                            }
                            float IconColumnWidth = IconSizes.Values.Max(x => x.Y);

                            //  Compute the size of each row (each row shows the effect of a type of augmentor that has been applied to this machine)
                            Dictionary <AugmentorType, Vector2> RowSizes = new Dictionary <AugmentorType, Vector2>();
                            foreach (KeyValuePair <AugmentorType, int> KVP in AttachedAugmentors.Where(x => x.Value > 0))
                            {
                                double  CurrentEffect = Augmentor.ComputeEffect(KVP.Key, KVP.Value, MI.RequiresInput);
                                string  Text          = string.Format("{0}% ({1})", (CurrentEffect * 100.0).ToString("0.#"), KVP.Value);
                                Vector2 TextSize      = DrawHelpers.MeasureStringWithSpecialNumbers(Text, 1.0f, 4.0f);

                                float RowWidth  = IconColumnWidth + MarginAfterIcon + TextSize.X;
                                float RowHeight = Math.Max(IconSizes[KVP.Key].Y, TextSize.Y);
                                RowSizes.Add(KVP.Key, new Vector2(RowWidth, RowHeight));
                            }

                            //  Compute total size of tooltip, draw the background
                            Vector2 ToolTipSize    = new Vector2(Padding * 2 + RowSizes.Values.Max(x => x.X), Padding * 2 + RowSizes.Values.Sum(x => x.Y));
                            Point   ToolTipTopleft = DrawHelpers.GetTopleftPosition(new Point((int)ToolTipSize.X, (int)ToolTipSize.Y), MouseScreenPosition, 100);
                            DrawHelpers.DrawBox(e.SpriteBatch, new Rectangle(ToolTipTopleft.X, ToolTipTopleft.Y, (int)ToolTipSize.X, (int)ToolTipSize.Y));
                            float CurrentY = ToolTipTopleft.Y + Padding;

                            //  Draw each row
                            float RowStartX = ToolTipTopleft.X + Padding;
                            foreach (KeyValuePair <AugmentorType, int> KVP in AttachedAugmentors.Where(x => x.Value > 0))
                            {
                                float CurrentX  = RowStartX;
                                float RowHeight = RowSizes[KVP.Key].Y;

                                //  Draw the icon
                                Augmentor.TryGetIconDetails(KVP.Key, out Texture2D IconTexture, out Rectangle IconSourcePosition, out float IconScale, out SpriteEffects IconEffects);
                                Vector2 IconSize     = IconSizes[KVP.Key];
                                Vector2 IconPosition = new Vector2(CurrentX + (IconColumnWidth - IconSize.X) / 2.0f, CurrentY + (RowHeight - IconSize.Y) / 2.0f);
                                e.SpriteBatch.Draw(IconTexture, IconPosition, IconSourcePosition, Color.White, 0f, Vector2.Zero, IconScale, IconEffects, 1f);
                                CurrentX += IconColumnWidth + MarginAfterIcon;

                                //  Draw the value
                                double  CurrentEffect = Augmentor.ComputeEffect(KVP.Key, KVP.Value, MI.RequiresInput);
                                string  Text          = string.Format("{0}% ({1})", (CurrentEffect * 100.0).ToString("0.#"), KVP.Value);
                                Vector2 TextSize      = DrawHelpers.MeasureStringWithSpecialNumbers(Text, 1.0f, 0.0f);
                                Vector2 TextPosition  = new Vector2(CurrentX, CurrentY + (RowHeight - TextSize.Y) / 2.0f);
                                DrawHelpers.DrawStringWithSpecialNumbers(e.SpriteBatch, TextPosition, Text, 1.0f, Color.White);

                                CurrentY += RowHeight;
                            }

                            //Maybe also show MinutesUntilReady if it's not ReadyForHarvest?
                        }
                    }
                }
            }
예제 #23
0
        public void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            if (!Config.EnableMod || !ShowingGrid || Game1.activeClickableMenu != null)
            {
                return;
            }

            string location = Game1.player.currentLocation.NameOrUniqueName;

            if (!utilitySystemDict.ContainsKey(location))
            {
                RemakeAllGroups(location);
            }
            Dictionary <Vector2, GridPipe> pipeDict = utilitySystemDict[location][CurrentGrid].pipes;
            List <PipeGroup> groupList = utilitySystemDict[location][CurrentGrid].groups;
            Dictionary <Vector2, UtilityObjectInstance> objectDict = utilitySystemDict[location][CurrentGrid].objects;
            Color color = CurrentGrid == GridType.electric ? Config.ElectricityColor : Config.WaterColor;

            foreach (var group in groupList)
            {
                Vector2 power       = GetGroupPower(location, group, CurrentGrid);
                Vector2 storedPower = GetGroupStoragePower(location, group, CurrentGrid);
                float   netPower    = power.X + power.Y;
                bool    powered     = power.X > 0 && netPower + storedPower.X >= 0;
                foreach (var pipe in group.pipes)
                {
                    if (Utility.isOnScreen(new Vector2(pipe.X * 64 + 32, pipe.Y * 64 + 32), 32))
                    {
                        if (pipeDict[pipe].index == 4)
                        {
                            DrawTile(e.SpriteBatch, pipe, new GridPipe()
                            {
                                index = 1, rotation = 2
                            }, powered ? color : Config.UnpoweredGridColor);
                        }
                        else
                        {
                            DrawTile(e.SpriteBatch, pipe, pipeDict[pipe], powered ? color : Config.UnpoweredGridColor);
                        }
                    }
                }
            }
            foreach (var kvp in objectDict)
            {
                DrawAmount(e.SpriteBatch, kvp, kvp.Value.CurrentPowerVector.X + kvp.Value.CurrentPowerVector.Y, color);
                DrawCharge(e.SpriteBatch, kvp, color);
            }
            if (ShowingEdit)
            {
                if (CurrentTile == 4)
                {
                    DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(-2, 2) / 64, new GridPipe()
                    {
                        index = 1, rotation = 2
                    }, Config.ShadowColor);
                    DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(-2, -2) / 64, new GridPipe()
                    {
                        index = 1, rotation = 2
                    }, Config.ShadowColor);
                    DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(2, -2) / 64, new GridPipe()
                    {
                        index = 1, rotation = 2
                    }, Config.ShadowColor);
                    DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(2, 2) / 64, new GridPipe()
                    {
                        index = 1, rotation = 2
                    }, Config.ShadowColor);
                    DrawTile(e.SpriteBatch, Game1.currentCursorTile, new GridPipe()
                    {
                        index = 1, rotation = 2
                    }, color);
                }
                else if (CurrentTile != 5)
                {
                    DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(-2, 2) / 64, new GridPipe()
                    {
                        index = CurrentTile, rotation = CurrentRotation
                    }, Config.ShadowColor);
                    DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(-2, -2) / 64, new GridPipe()
                    {
                        index = CurrentTile, rotation = CurrentRotation
                    }, Config.ShadowColor);
                    DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(2, -2) / 64, new GridPipe()
                    {
                        index = CurrentTile, rotation = CurrentRotation
                    }, Config.ShadowColor);
                    DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(2, 2) / 64, new GridPipe()
                    {
                        index = CurrentTile, rotation = CurrentRotation
                    }, Config.ShadowColor);
                    DrawTile(e.SpriteBatch, Game1.currentCursorTile, new GridPipe()
                    {
                        index = CurrentTile, rotation = CurrentRotation
                    }, color);
                }
                if (Helper.Input.IsDown(Config.PlaceTile) || Helper.Input.IsSuppressed(Config.PlaceTile))
                {
                    if (lastCursorTile != Game1.lastCursorTile)
                    {
                        Helper.Input.Suppress(Config.PlaceTile);
                        lastCursorTile = Game1.lastCursorTile;
                        if (pipeDict.ContainsKey(Game1.lastCursorTile))
                        {
                            if (!PayForPipe(true))
                            {
                                return;
                            }
                            Monitor.Log($"Removing tile at {Game1.currentCursorTile}");
                        }
                        else if (!PayForPipe(false))
                        {
                            return;
                        }

                        Monitor.Log($"Placing tile {CurrentTile},{CurrentRotation} at {Game1.currentCursorTile}");
                        pipeDict[Game1.lastCursorTile] = new GridPipe()
                        {
                            index = CurrentTile, rotation = CurrentRotation
                        };
                        if (Config.PipeSound?.Length > 0)
                        {
                            Game1.player.currentLocation.playSound(Config.PipeSound);
                        }
                        RemakeGroups(location, CurrentGrid);
                    }
                }
                else
                {
                    lastCursorTile = new Vector2(-1, -1);
                }
            }
        }