From 7f1a652de6a02425fb84f8906166861c9cb2136f Mon Sep 17 00:00:00 2001 From: dazedanon Date: Sat, 20 Dec 2025 11:33:23 -0600 Subject: [PATCH] Mod in minimap (o button) --- js/plugins.js | 8 + js/plugins/MinimapZoom.js | 368 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 376 insertions(+) create mode 100644 js/plugins/MinimapZoom.js diff --git a/js/plugins.js b/js/plugins.js index af70f90..609ac79 100644 --- a/js/plugins.js +++ b/js/plugins.js @@ -2543,4 +2543,12 @@ var $plugins = [ description: "Adds F9 keybind to refresh text variables with updated translations", parameters: {}, }, + { + name: "MinimapZoom", + status: true, + description: "Press O to toggle a zoomed-out minimap view of the current map", + parameters: { + "Toggle Key": "79", + }, + }, ]; diff --git a/js/plugins/MinimapZoom.js b/js/plugins/MinimapZoom.js new file mode 100644 index 0000000..160de82 --- /dev/null +++ b/js/plugins/MinimapZoom.js @@ -0,0 +1,368 @@ +//============================================================================= +// MinimapZoom.js +//============================================================================= + +/*: + * @plugindesc Adds a minimap/zoom-out feature. Press O to toggle a zoomed-out view of the entire map. + * @author Dazed Translations + * + * @param Toggle Key + * @desc The key to toggle minimap (keycode: O = 79) + * @default 79 + * + * @help + * Press the O key while on the map to toggle a zoomed-out minimap view. + * Shows the entire map scaled to fit the screen. + * Character sprites are hidden, and a marker shows your position. + * Press O again to return to normal view. + */ + +(function() { + 'use strict'; + + // Plugin parameters + const pluginName = 'MinimapZoom'; + const parameters = PluginManager.parameters(pluginName); + const toggleKeyCode = Number(parameters['Toggle Key'] || 79); // O key + + // Track minimap state + let minimapActive = false; + + //========================================================================= + // Input - Add minimap key + //========================================================================= + + Input.keyMapper[toggleKeyCode] = 'minimap'; + + //========================================================================= + // Scene_Map - Handle minimap toggle + //========================================================================= + + const _Scene_Map_update = Scene_Map.prototype.update; + Scene_Map.prototype.update = function() { + _Scene_Map_update.call(this); + this.updateMinimapToggle(); + }; + + Scene_Map.prototype.updateMinimapToggle = function() { + // Only allow toggle when not busy with messages/menus + if (Input.isTriggered('minimap') && !$gameMessage.isBusy()) { + this.toggleMinimap(); + } + + // Update player marker position if minimap is active + if (minimapActive && this._minimapPlayerMarker) { + this.updateMinimapPlayerMarker(); + } + }; + + Scene_Map.prototype.toggleMinimap = function() { + minimapActive = !minimapActive; + + if (minimapActive) { + this.showMinimap(); + SoundManager.playCursor(); + } else { + this.hideMinimap(); + SoundManager.playCancel(); + } + }; + + Scene_Map.prototype.showMinimap = function() { + if (!this._spriteset) return; + + // Hide the normal spriteset + this._spriteset.visible = false; + + // Create minimap overlay + this.createMinimapOverlay(); + }; + + Scene_Map.prototype.hideMinimap = function() { + if (!this._spriteset) return; + + // Show the normal spriteset + this._spriteset.visible = true; + + // Remove minimap overlay + this.removeMinimapOverlay(); + }; + + Scene_Map.prototype.createMinimapOverlay = function() { + if (this._minimapOverlay) return; + + // Create container for minimap + this._minimapOverlay = new Sprite(); + this._minimapOverlay.bitmap = new Bitmap(Graphics.width, Graphics.height); + + // Fill background + this._minimapOverlay.bitmap.fillRect(0, 0, Graphics.width, Graphics.height, '#000000'); + + // Get map dimensions + const mapWidth = $gameMap.width(); + const mapHeight = $gameMap.height(); + const tileWidth = $gameMap.tileWidth(); + const tileHeight = $gameMap.tileHeight(); + + // Calculate scale to fit entire map on screen with padding + const padding = 60; + const availableWidth = Graphics.width - padding * 2; + const availableHeight = Graphics.height - padding * 2; + + const mapPixelWidth = mapWidth * tileWidth; + const mapPixelHeight = mapHeight * tileHeight; + + const scaleX = availableWidth / mapPixelWidth; + const scaleY = availableHeight / mapPixelHeight; + const scale = Math.min(scaleX, scaleY, 1); // Don't zoom in past 1x + + const scaledWidth = mapPixelWidth * scale; + const scaledHeight = mapPixelHeight * scale; + + // Center the map + const offsetX = (Graphics.width - scaledWidth) / 2; + const offsetY = (Graphics.height - scaledHeight) / 2; + + // Store for marker positioning + this._minimapScale = scale; + this._minimapOffsetX = offsetX; + this._minimapOffsetY = offsetY; + this._minimapTileWidth = tileWidth; + this._minimapTileHeight = tileHeight; + + // Create the map snapshot sprite + this._minimapContent = new Sprite(); + this._minimapContent.x = offsetX; + this._minimapContent.y = offsetY; + this._minimapContent.scale.x = scale; + this._minimapContent.scale.y = scale; + + // Render the tilemap to a bitmap + this.renderMinimapTiles(); + + // Draw border around map + const ctx = this._minimapOverlay.bitmap.context; + ctx.strokeStyle = '#FFFFFF'; + ctx.lineWidth = 2; + ctx.strokeRect(offsetX - 2, offsetY - 2, scaledWidth + 4, scaledHeight + 4); + + // Add title text + this._minimapOverlay.bitmap.fontSize = 24; + this._minimapOverlay.bitmap.textColor = '#FFFFFF'; + this._minimapOverlay.bitmap.outlineColor = '#000000'; + this._minimapOverlay.bitmap.outlineWidth = 4; + this._minimapOverlay.bitmap.drawText('MAP VIEW - Press O to close', 0, 10, Graphics.width, 30, 'center'); + + // Add map name + const mapName = $gameMap.displayName() || ('Map ' + $gameMap.mapId()); + this._minimapOverlay.bitmap.fontSize = 18; + this._minimapOverlay.bitmap.drawText(mapName, 0, Graphics.height - 35, Graphics.width, 24, 'center'); + + this.addChild(this._minimapOverlay); + this.addChild(this._minimapContent); + + // Create player marker + this.createMinimapPlayerMarker(); + }; + + Scene_Map.prototype.renderMinimapTiles = function() { + const mapWidth = $gameMap.width(); + const mapHeight = $gameMap.height(); + const tileWidth = $gameMap.tileWidth(); + const tileHeight = $gameMap.tileHeight(); + + // Create bitmap for the map + const bitmap = new Bitmap(mapWidth * tileWidth, mapHeight * tileHeight); + this._minimapContent.bitmap = bitmap; + + // Get tileset + const tileset = $gameMap.tileset(); + if (!tileset) return; + + // Simple tile rendering - draw colored rectangles based on passability + for (let y = 0; y < mapHeight; y++) { + for (let x = 0; x < mapWidth; x++) { + const px = x * tileWidth; + const py = y * tileHeight; + + // Check tile properties + const isPassable = $gameMap.isPassable(x, y, 2) || + $gameMap.isPassable(x, y, 4) || + $gameMap.isPassable(x, y, 6) || + $gameMap.isPassable(x, y, 8); + + // Get terrain tag for variety + const terrainTag = $gameMap.terrainTag(x, y); + const regionId = $gameMap.regionId(x, y); + + // Color based on passability and terrain + let color; + if (!isPassable) { + // Impassable - walls, obstacles + color = '#4a4a4a'; + } else if (terrainTag > 0) { + // Special terrain + const terrainColors = ['#5b8a5b', '#6b9b6b', '#4a7a7a', '#7a6a5a', '#5a6a7a', '#7a5a6a', '#6a7a5a']; + color = terrainColors[(terrainTag - 1) % terrainColors.length]; + } else { + // Normal passable floor + color = '#7a9a7a'; + } + + // Add some variation based on position + if ((x + y) % 2 === 0) { + color = this.adjustColor(color, 10); + } + + bitmap.fillRect(px, py, tileWidth, tileHeight, color); + + // Draw subtle grid + bitmap.fillRect(px, py, tileWidth, 1, 'rgba(0,0,0,0.1)'); + bitmap.fillRect(px, py, 1, tileHeight, 'rgba(0,0,0,0.1)'); + } + } + + // Draw events as markers + for (const event of $gameMap.events()) { + if (event && event.characterName()) { + const ex = event.x * tileWidth + tileWidth / 2; + const ey = event.y * tileHeight + tileHeight / 2; + + // Draw event marker + const ctx = bitmap.context; + ctx.fillStyle = '#FFD700'; + ctx.beginPath(); + ctx.arc(ex, ey, Math.min(tileWidth, tileHeight) / 3, 0, Math.PI * 2); + ctx.fill(); + ctx.strokeStyle = '#000000'; + ctx.lineWidth = 1; + ctx.stroke(); + } + } + }; + + Scene_Map.prototype.adjustColor = function(hex, amount) { + // Simple color adjustment + let r = parseInt(hex.slice(1, 3), 16); + let g = parseInt(hex.slice(3, 5), 16); + let b = parseInt(hex.slice(5, 7), 16); + + r = Math.min(255, Math.max(0, r + amount)); + g = Math.min(255, Math.max(0, g + amount)); + b = Math.min(255, Math.max(0, b + amount)); + + return '#' + r.toString(16).padStart(2, '0') + + g.toString(16).padStart(2, '0') + + b.toString(16).padStart(2, '0'); + }; + + Scene_Map.prototype.createMinimapPlayerMarker = function() { + if (this._minimapPlayerMarker) return; + + // Create player marker sprite + this._minimapPlayerMarker = new Sprite(); + this._minimapPlayerMarker.bitmap = new Bitmap(32, 32); + + // Draw a bright marker + const ctx = this._minimapPlayerMarker.bitmap.context; + + // Outer glow + ctx.fillStyle = '#FF0000'; + ctx.beginPath(); + ctx.arc(16, 16, 12, 0, Math.PI * 2); + ctx.fill(); + + // Inner bright + ctx.fillStyle = '#FFFF00'; + ctx.beginPath(); + ctx.arc(16, 16, 8, 0, Math.PI * 2); + ctx.fill(); + + // Center dot + ctx.fillStyle = '#FFFFFF'; + ctx.beginPath(); + ctx.arc(16, 16, 4, 0, Math.PI * 2); + ctx.fill(); + + this._minimapPlayerMarker.anchor.x = 0.5; + this._minimapPlayerMarker.anchor.y = 0.5; + + this.addChild(this._minimapPlayerMarker); + this.updateMinimapPlayerMarker(); + }; + + Scene_Map.prototype.updateMinimapPlayerMarker = function() { + if (!this._minimapPlayerMarker) return; + + const playerX = $gamePlayer.x; + const playerY = $gamePlayer.y; + + // Calculate marker position + const markerX = this._minimapOffsetX + (playerX + 0.5) * this._minimapTileWidth * this._minimapScale; + const markerY = this._minimapOffsetY + (playerY + 0.5) * this._minimapTileHeight * this._minimapScale; + + this._minimapPlayerMarker.x = markerX; + this._minimapPlayerMarker.y = markerY; + + // Pulse effect + const pulse = Math.sin(Graphics.frameCount * 0.1) * 0.2 + 1; + this._minimapPlayerMarker.scale.x = pulse; + this._minimapPlayerMarker.scale.y = pulse; + }; + + Scene_Map.prototype.removeMinimapOverlay = function() { + if (this._minimapOverlay) { + this.removeChild(this._minimapOverlay); + this._minimapOverlay = null; + } + if (this._minimapContent) { + this.removeChild(this._minimapContent); + this._minimapContent = null; + } + if (this._minimapPlayerMarker) { + this.removeChild(this._minimapPlayerMarker); + this._minimapPlayerMarker = null; + } + }; + + //========================================================================= + // Handle scene transitions - Reset minimap when leaving map + //========================================================================= + + const _Scene_Map_terminate = Scene_Map.prototype.terminate; + Scene_Map.prototype.terminate = function() { + if (minimapActive) { + this.hideMinimap(); + minimapActive = false; + } + _Scene_Map_terminate.call(this); + }; + + //========================================================================= + // Prevent menu/actions while minimap is active + //========================================================================= + + const _Scene_Map_isMenuEnabled = Scene_Map.prototype.isMenuEnabled; + Scene_Map.prototype.isMenuEnabled = function() { + if (minimapActive) return false; + return _Scene_Map_isMenuEnabled.call(this); + }; + + const _Scene_Map_isMapTouchOk = Scene_Map.prototype.isMapTouchOk; + Scene_Map.prototype.isMapTouchOk = function() { + if (minimapActive) return false; + return _Scene_Map_isMapTouchOk.call(this); + }; + + const _Game_Player_canMove = Game_Player.prototype.canMove; + Game_Player.prototype.canMove = function() { + if (minimapActive) return false; + return _Game_Player_canMove.call(this); + }; + + // Public accessor for minimap state + Scene_Map.prototype.isMinimapActive = function() { + return minimapActive; + }; + +})();