diff --git a/js/plugins/MinimapZoom.js b/js/plugins/MinimapZoom.js index 86f8609..b74b80c 100644 --- a/js/plugins/MinimapZoom.js +++ b/js/plugins/MinimapZoom.js @@ -158,6 +158,9 @@ this._minimapOverlay.bitmap.fontSize = 18; this._minimapOverlay.bitmap.drawText(mapName, 0, Graphics.height - 35, Graphics.width, 24, 'center'); + // Draw legend + this.drawMinimapLegend(); + this.addChild(this._minimapOverlay); this.addChild(this._minimapContent); @@ -165,6 +168,63 @@ this.createMinimapPlayerMarker(); }; + Scene_Map.prototype.drawMinimapLegend = function() { + const bitmap = this._minimapOverlay.bitmap; + const legendX = 15; + const legendY = 45; + const dotSize = 8; + const lineHeight = 22; + const ctx = bitmap.context; + + bitmap.fontSize = 14; + bitmap.textColor = '#FFFFFF'; + bitmap.outlineColor = '#000000'; + bitmap.outlineWidth = 3; + + // Legend title + bitmap.drawText('LEGEND:', legendX, legendY, 100, 18, 'left'); + + // Player marker + ctx.fillStyle = '#FF0000'; + ctx.beginPath(); + ctx.arc(legendX + dotSize/2, legendY + lineHeight + dotSize/2, dotSize/2, 0, Math.PI * 2); + ctx.fill(); + ctx.strokeStyle = '#FFFF00'; + ctx.lineWidth = 2; + ctx.stroke(); + bitmap.drawText('You', legendX + dotSize + 8, legendY + lineHeight, 100, 18, 'left'); + + // NPC marker (gold) + ctx.fillStyle = '#FFD700'; + ctx.beginPath(); + ctx.arc(legendX + dotSize/2, legendY + lineHeight * 2 + dotSize/2, dotSize/2, 0, Math.PI * 2); + ctx.fill(); + ctx.strokeStyle = '#000000'; + ctx.lineWidth = 1; + ctx.stroke(); + bitmap.drawText('NPC', legendX + dotSize + 8, legendY + lineHeight * 2, 100, 18, 'left'); + + // Locked door/chest marker (cyan) + ctx.fillStyle = '#00FFFF'; + ctx.beginPath(); + ctx.arc(legendX + dotSize/2, legendY + lineHeight * 3 + dotSize/2, dotSize/2, 0, Math.PI * 2); + ctx.fill(); + ctx.strokeStyle = '#000000'; + ctx.lineWidth = 1; + ctx.stroke(); + bitmap.drawText('Locked', legendX + dotSize + 8, legendY + lineHeight * 3, 150, 18, 'left'); + + // Exit/Transfer marker (green) + ctx.fillStyle = '#00FF00'; + ctx.beginPath(); + ctx.arc(legendX + dotSize/2, legendY + lineHeight * 4 + dotSize/2, dotSize/2, 0, Math.PI * 2); + ctx.fill(); + ctx.strokeStyle = '#000000'; + ctx.lineWidth = 1; + ctx.stroke(); + bitmap.drawText('Exit/Entrance', legendX + dotSize + 8, legendY + lineHeight * 4, 150, 18, 'left'); + }; + Scene_Map.prototype.renderMinimapTiles = function() { const mapWidth = $gameMap.width(); const mapHeight = $gameMap.height(); @@ -222,14 +282,35 @@ } } - // Draw important events as markers (NPCs only, not decorations) + // Draw important events as markers for (const event of $gameMap.events()) { - if (event && this.isImportantEvent(event)) { - const ex = event.x * tileWidth + tileWidth / 2; - const ey = event.y * tileHeight + tileHeight / 2; - - // Draw event marker - const ctx = bitmap.context; + if (!event) continue; + + const ex = event.x * tileWidth + tileWidth / 2; + const ey = event.y * tileHeight + tileHeight / 2; + const ctx = bitmap.context; + + // Check event types in priority order + if (this.isLockedDoorOrChest(event)) { + // Draw locked door/chest marker (cyan) + ctx.fillStyle = '#00FFFF'; + 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(); + } else if (this.isMapTransfer(event)) { + // Draw exit/entrance marker (green) + ctx.fillStyle = '#00FF00'; + 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(); + } else if (this.isImportantEvent(event)) { + // Draw NPC marker (gold) ctx.fillStyle = '#FFD700'; ctx.beginPath(); ctx.arc(ex, ey, Math.min(tileWidth, tileHeight) / 3, 0, Math.PI * 2); @@ -241,6 +322,62 @@ } }; + // Check if an event is a locked door, chest, or barred gate + Scene_Map.prototype.isLockedDoorOrChest = function(event) { + if (!event) return false; + + // Get the event data + const eventData = event.event(); + if (!eventData) return false; + + const name = eventData.name; + + // Check for locked door patterns + if (name.includes('鍵扉')) return true; // "Locked door" + + // Check for chest patterns + if (name.includes('宝箱')) return true; // "Treasure chest" + + // Check for barred door/gate patterns + if (name.includes('鉄格子')) return true; // "Iron bars/Barred gate" + + return false; + }; + + // Check if an event transfers to another map + Scene_Map.prototype.isMapTransfer = function(event) { + if (!event) return false; + + // Get the event data + const eventData = event.event(); + if (!eventData) return false; + + const name = eventData.name; + + // Check for transfer event name patterns + if (name.includes('移動')) return true; // "Transfer/Move" + + // Check the current page for Transfer Player command (code 201) + const page = event.page(); + if (!page) return false; + + const list = page.list; + if (!list) return false; + + for (const cmd of list) { + if (cmd.code === 201) { // Transfer Player command + return true; + } + } + + return false; + }; + + // Check if an event is a locked door that can be picked (legacy - kept for compatibility) + Scene_Map.prototype.isLockedDoor = function(event) { + return this.isLockedDoorOrChest(event); + }; + // Determine if an event is "important" (NPC, not decoration/ambient) Scene_Map.prototype.isImportantEvent = function(event) { if (!event) return false;