-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmap.html
More file actions
261 lines (222 loc) · 18.1 KB
/
Copy pathmap.html
File metadata and controls
261 lines (222 loc) · 18.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>EAHA | Tactical Map</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/svg+xml" href="favicon.svg">
<link rel="stylesheet" href="style.css">
<style>
/* Map-Specific Tactical CSS */
.map-window { position: relative; width: 100%; background: #000; overflow: hidden; border-radius: 12px; border: 1px solid var(--border); box-shadow: inset 0 0 20px rgba(0,0,0,0.8); cursor: grab; }
.map-window:active { cursor: grabbing; }
.map-window.pin-mode { cursor: crosshair; }
.map-window.route-mode { cursor: crosshair; }
.map-window.ruler-mode { cursor: crosshair; }
.map-window.ping-mode { cursor: crosshair; } /* JARVIS UPGRADE */
#mapTransform { position: absolute; top: 0; left: 0; width: 100%; height: 100%; transform-origin: 0 0; transition: transform 0.1s cubic-bezier(0.2, 0, 0, 1); }
#mapImage { display: block; width: 100%; height: 100%; object-fit: contain; object-position: center; }
#pinLayer { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }
.map-pin { position: absolute; transform: translate(-50%, -100%); font-size: calc(24px / var(--map-scale, 1)); text-shadow: 0 2px 4px rgba(0,0,0,0.8); pointer-events: auto; cursor: pointer; z-index: 10; transition: transform 0.1s; filter: drop-shadow(0px 4px 6px rgba(0,0,0,0.6)); }
.map-pin:hover { transform: translate(-50%, -110%) scale(1.2); z-index: 20; filter: drop-shadow(0px 6px 10px rgba(16,185,129,0.8)); }
.map-pin.live-pin { animation: pulseLive 2s infinite; filter: drop-shadow(0px 0px 8px rgba(16, 185, 129, 0.8)); }
@keyframes pulseLive { 0% { transform: translate(-50%, -100%) scale(1); } 50% { transform: translate(-50%, -100%) scale(1.15); filter: drop-shadow(0px 0px 12px rgba(16, 185, 129, 1)); } 100% { transform: translate(-50%, -100%) scale(1); } }
.pin-label { position: absolute; bottom: 110%; left: 50%; transform: translateX(-50%); background: rgba(15, 23, 42, 0.9); border: 1px solid var(--primary); padding: 4px 10px; border-radius: 6px; font-size: calc(12px / var(--map-scale, 1)); font-weight: bold; white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity 0.2s, bottom 0.2s; box-shadow: 0 4px 10px rgba(0,0,0,0.5); color: #fff; }
.map-pin:hover .pin-label { opacity: 1; bottom: 130%; }
/* JARVIS UPGRADE: Tactical Map Ping Radar Animation */
.map-ping { position: absolute; width: 40px; height: 40px; border: 2px solid var(--info); background: color-mix(in srgb, var(--info) 30%, transparent); border-radius: 50%; transform: translate(-50%, -50%) scale(0); animation: radarPing 2.5s cubic-bezier(0.2, 0.8, 0.2, 1) infinite; pointer-events: none; z-index: 40; }
.map-ping .pin-label { display: block; opacity: 1; bottom: 120%; background: var(--info); color: #000; pointer-events: none; white-space: nowrap; }
@keyframes radarPing { 0% { transform: translate(-50%, -50%) scale(0.5); opacity: 1; } 100% { transform: translate(-50%, -50%) scale(3); opacity: 0; } }
@keyframes slideInRight { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
.danger-zone { position: absolute; border-radius: 50%; pointer-events: none; transform: translate(-50%, -50%); border: 3px solid; z-index: 5; box-shadow: inset 0 0 20px rgba(0,0,0,0.3); }
.route-node { position: absolute; border-radius: 50%; background: var(--warning); border: 2px solid #fff; pointer-events: auto; z-index: 30; box-shadow: 0 2px 4px rgba(0,0,0,0.8); transition: transform 0.1s; cursor: grab; }
.route-node:active { cursor: grabbing; transform: translate(-50%, -50%) scale(1.3) !important; }
#routeLayer { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
#activeRoutePolyline { fill: none; stroke: var(--danger); stroke-width: calc(0.6 / var(--map-scale, 1)); stroke-dasharray: calc(1.5 / var(--map-scale, 1)); animation: march calc(2s * var(--map-scale, 1)) linear infinite; filter: drop-shadow(0 0 1px rgba(239, 68, 68, 0.8)); }
@keyframes march { to { stroke-dashoffset: -3; } }
.hud-display { position: absolute; top: 15px; left: 15px; background: rgba(15, 23, 42, 0.85); border: 1px solid var(--primary); padding: 8px 12px; border-radius: 8px; color: var(--primary); font-size: 0.9em; font-family: monospace; z-index: 100; box-shadow: 0 4px 10px rgba(0,0,0,0.6); backdrop-filter: blur(4px); pointer-events: auto; cursor: pointer; transition: all 0.2s; user-select: none; }
.hud-display:hover { background: rgba(15, 23, 42, 0.95); transform: translateY(-2px); box-shadow: 0 6px 12px rgba(16, 185, 129, 0.4); border-color: #10b981; }
.hud-display .copy-hint { font-size: 0.75em; opacity: 0.6; margin-left: 10px; transition: opacity 0.2s; }
.hud-display:hover .copy-hint { opacity: 1; color: #10b981; }
.zoom-controls { position: absolute; bottom: 20px; right: 20px; display: flex; flex-direction: column; gap: 8px; z-index: 100; }
.zoom-btn { background: rgba(30, 41, 59, 0.85); color: white; border: 1px solid var(--border); width: 45px; height: 45px; border-radius: 12px; font-size: 1.5rem; font-weight: bold; cursor: pointer; backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; transition: all 0.2s; box-shadow: 0 4px 10px rgba(0,0,0,0.5); }
.zoom-btn:hover { background: var(--primary); transform: translateY(-2px); border-color: var(--primary); }
.modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); backdrop-filter: blur(5px); z-index: 9999; display: flex; justify-content: center; align-items: center; }
.color-picker-grid { display: flex; gap: 12px; margin-top: 8px; flex-wrap: wrap; }
.color-swatch { width: 36px; height: 36px; border-radius: 50%; border: 3px solid transparent; cursor: pointer; transition: transform 0.15s, border-color 0.15s; outline: none; }
.color-swatch:hover { transform: scale(1.1); }
.color-swatch.active { border-color: #fff; transform: scale(1.15); box-shadow: 0 0 10px rgba(255,255,255,0.4); }
</style>
</head>
<body>
<div id="killfeedContainer" style="position: fixed; top: 80px; right: 20px; z-index: 9999; display: flex; flex-direction: column; gap: 8px; pointer-events: none;"></div>
<header class="top-nav">
<div class="nav-header">
<div class="brand">Elys Astra Helper Application</div>
<button class="mobile-menu-btn" onclick="document.querySelector('.nav-links').classList.toggle('active')">☰</button>
</div>
<nav class="nav-links">
<a class="nav-btn" href="index.html">Dashboard</a>
<a class="nav-btn" href="apps.html">Post Builder</a>
<a class="nav-btn" href="work.html">Rules & Guidelines</a>
<a class="nav-btn" href="docs.html">Creature Profiles</a>
<a class="nav-btn" href="about.html">Stats</a>
<a class="nav-btn" href="combat.html">Combat Log</a>
<a class="nav-btn active" href="map.html">Tactical Map</a>
<a class="nav-btn" href="lineage.html">Lineage</a>
<a class="nav-btn" href="settings.html">Settings</a>
<a class="nav-btn" href="guide.html">System Manual</a>
</nav>
</header>
<main class="page builder-workspace">
<aside class="preset-sidebar card" style="border-top: 5px solid var(--info);">
<h2 style="font-size: 1.5em; margin-bottom: 10px;">Recon Data</h2>
<p class="muted" style="margin-bottom: 15px; font-size: 0.9em; line-height: 1.4;">Your saved tactical markers and migration routes.</p>
<div class="field" style="margin-bottom: 15px; background: var(--bg-alt); padding: 10px; border-radius: 8px; border: 1px solid var(--border);">
<label style="font-weight: 600; color: var(--primary); font-size: 0.85em; display: block; margin-bottom: 5px;">Active Operator Recon</label>
<select id="mapCreatureSelect" class="full-width" style="cursor: pointer; background: var(--bg); border: 1px solid var(--border);">
<option value="global">🌍 Global Roster (All Data)</option>
</select>
</div>
<div style="display: flex; gap: 5px; margin-bottom: 15px;">
<button class="btn btn-sm full-width" id="exportReconBtn" style="background: var(--info);">📤 Export</button>
<button class="btn btn-sm btn-ghost full-width" id="importReconBtn" style="color: var(--info); border-color: var(--info);">📥 Import</button>
</div>
<div class="field" style="margin-bottom: 10px;">
<input type="text" id="pinSearch" placeholder="Search markers...">
</div>
<div class="field" style="margin-bottom: 15px;">
<select id="pinFilter">
<option value="all">All Marker Types</option>
<option value="📍">📍 General</option>
<option value="⚔️">⚔️ PvP Kill / Death</option>
<option value="🥩">🥩 Food Source</option>
<option value="💧">💧 Water Source</option>
<option value="☠️">☠️ High Danger Zone</option>
<option value="⛺">⛺ Safe Zone / Homecave</option>
<option value="🎯">🎯 Group Rally Point</option>
<option value="🌿">🌿 Resource Node</option>
</select>
</div>
<div id="pinList" class="preset-list" style="margin-bottom: 20px; max-height: 300px; overflow-y: auto;"></div>
<button class="btn btn-ghost btn-sm full-width" id="clearAllPinsBtn" style="color: var(--danger); border-color: var(--danger);">⚠️ Clear Active Markers</button>
<hr style="border-color: var(--border); margin: 20px 0;">
<h3 style="color: var(--primary); margin-bottom: 10px; font-size: 1.2em;">Saved Routes</h3>
<div id="routeList" class="preset-list" style="max-height: 200px; overflow-y: auto;"></div>
</aside>
<section class="editor-pane scrollable" style="flex: 2;">
<div class="card" style="border-top: 5px solid var(--primary); margin-bottom: 15px;">
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;">
<h2 style="margin: 0; color: var(--primary);">Gondwa Tactical Map</h2>
<div class="chip-group" style="margin: 0;">
<button class="chip active" id="modePanBtn" style="background: var(--primary); color: white; border-color: var(--primary);">🤚 Nav</button>
<button class="chip" id="modePinBtn">📍 Deploy</button>
<button class="chip" id="modePingBtn" style="color: var(--info); border-color: var(--info);">📡 Ping</button>
<button class="chip" id="modeRouteBtn">🛤️ Route</button>
<button class="chip" id="modeRulerBtn">📏 Measure</button>
<button class="chip" id="sosDistressBtn" style="background: var(--danger); color: white; border-color: var(--danger); display: none; font-weight: bold; animation: pulseLive 2s infinite;">🚨 SOS</button>
</div>
</div>
<div id="routeTools" class="is-hidden" style="margin-top: 15px; padding-top: 15px; border-top: 1px solid var(--border); display: flex; gap: 10px; align-items: center;">
<span style="font-weight: bold; color: var(--danger);">🔴 Active Route Planning</span>
<div style="margin-left: auto; display: flex; gap: 10px;">
<button class="btn btn-sm" id="saveRouteBtn" style="background: var(--success);">Save Route</button>
<button class="btn btn-sm btn-ghost" id="cancelRouteBtn">Cancel</button>
</div>
</div>
<div id="calibrationTools" class="is-hidden" style="margin-top: 15px; padding: 15px; background: color-mix(in srgb, var(--warning) 20%, transparent); border-radius: 8px; border: 1px solid var(--warning); display: flex; gap: 10px; align-items: center;">
<span style="font-weight: bold; color: var(--warning);">⚙️ Calibration Mode: Drag the gear to your exact visual location.</span>
<div style="margin-left: auto; display: flex; gap: 10px;">
<button class="btn btn-sm" id="confirmDeployBtn" style="background: var(--success);">Confirm Offset</button>
<button class="btn btn-sm btn-ghost" id="cancelDeployBtn" style="color: var(--danger); border-color: var(--danger);">Abort</button>
</div>
</div>
</div>
<div class="card" style="margin-bottom: 15px; padding: 15px; display: flex; gap: 10px; flex-wrap: wrap; border-top: 3px solid var(--info);">
<input type="text" id="mobileCoordInput" placeholder="Mobile: Paste X=... Y=... coordinates here" style="flex: 1; min-width: 200px;">
<button class="btn" id="mobileCoordBtn" style="border-color: var(--border);">📍 Plot</button>
<button class="btn" id="pingCoordBtn" style="background: var(--info); border-color: var(--info);">📡 Ping Loc</button>
<button class="btn btn-ghost" id="recalibrateBtn" style="color: var(--warning); border-color: var(--warning); margin-left: auto;">⚙️ Calibrate GPS</button>
</div>
<div class="map-window" id="mapWindow">
<div id="mapTransform">
<img id="mapImage" src="gondwa.jpg" alt="Gondwa Map" draggable="false">
<svg id="routeLayer" viewBox="0 0 100 100" preserveAspectRatio="none">
<polyline id="activeRoutePolyline" />
<line id="rulerLine" x1="0" y1="0" x2="0" y2="0" stroke="var(--info)" stroke-width="0.3" stroke-dasharray="1" style="display:none; pointer-events:none; filter: drop-shadow(0 0 1px rgba(56, 189, 248, 0.8));" />
</svg>
<div id="pinLayer"></div>
</div>
<div class="zoom-controls">
<button class="zoom-btn" id="zoomInBtn">+</button>
<button class="zoom-btn" id="resetZoomBtn" style="font-size: 1rem;">⟲</button>
<button class="zoom-btn" id="zoomOutBtn">-</button>
</div>
</div>
<p class="muted" style="font-size: 0.85em; text-align: center; margin-top: 10px;">
Desktop: Press Ctrl+V with a map screenshot or raw text to auto-plot your location.
</p>
</section>
</main>
<div id="pinModal" class="modal-overlay is-hidden">
<div class="card" style="width: 100%; max-width: 400px; margin: 20px; position: relative; border-top: 5px solid var(--primary);">
<h2 id="pinModalTitle" style="color: var(--primary); margin-bottom: 20px; border-bottom: 2px solid var(--border); padding-bottom: 10px;">Deploy Tactical Marker</h2>
<div class="form-grid">
<label class="field">
<span>Marker Type</span>
<select id="newPinType">
<option value="📍">📍 General</option>
<option value="⚔️">⚔️ PvP Kill / Death</option>
<option value="🥩">🥩 Food Source</option>
<option value="💧">💧 Water Source</option>
<option value="☠️">☠️ High Danger Zone</option>
<option value="⛺">⛺ Safe Zone / Homecave</option>
<option value="🎯">🎯 Group Rally Point</option>
<option value="🌿">🌿 Resource Node</option>
</select>
</label>
<label class="field">
<span>Label / Notes (Optional)</span>
<input type="text" id="newPinLabel" placeholder="e.g., Rex Corpse, Hidden Cave">
</label>
<label class="field">
<span>Danger Zone Radius (Meters) - Optional</span>
<input type="number" id="newPinRadius" placeholder="e.g. 500" min="0">
</label>
<label class="field" style="margin-top: 10px;">
<span>Zone Color</span>
<div class="color-picker-grid" id="colorPickerGrid">
<button type="button" class="color-swatch active" data-color="#ef4444" style="background: #ef4444;" title="Red"></button>
<button type="button" class="color-swatch" data-color="#f59e0b" style="background: #f59e0b;" title="Yellow"></button>
<button type="button" class="color-swatch" data-color="#10b981" style="background: #10b981;" title="Green"></button>
<button type="button" class="color-swatch" data-color="#3b82f6" style="background: #3b82f6;" title="Blue"></button>
<button type="button" class="color-swatch" data-color="#8b5cf6" style="background: #8b5cf6;" title="Purple"></button>
<button type="button" class="color-swatch" data-color="#f8fafc" style="background: #f8fafc;" title="White"></button>
</div>
<input type="hidden" id="newPinColor" value="#ef4444">
</label>
<label class="field is-hidden" id="broadcastPinWrapper" style="margin-top: 10px; padding: 10px; background: color-mix(in srgb, var(--success) 10%, transparent); border: 1px solid var(--success); border-radius: 8px;">
<span style="color: var(--success); font-weight: bold; display: flex; align-items: center; gap: 8px;">
<input type="checkbox" id="broadcastPinToggle" style="transform: scale(1.2);"> Broadcast to Live Pack
</span>
</label>
<div style="display: flex; gap: 10px; margin-top: 15px;">
<button class="btn full-width" id="savePinBtn">Save Marker</button>
<button class="btn btn-ghost full-width" id="cancelPinBtn">Cancel</button>
</div>
</div>
</div>
</div>
<div id="toast" class="toast" role="status" aria-live="polite"></div>
<footer style="text-align: center; padding: 20px; color: var(--muted); font-size: 0.9em;">© 2026 EAHA All Rights Reserved, Engineered by PixelPacket</footer>
<script type="module" src="data-store.js"></script>
<script type="module" src="map.js"></script>
<script type="module">
import { auth } from './data-store.js';
import { onAuthStateChanged } from "https://www.gstatic.com/firebasejs/10.8.0/firebase-auth.js";
onAuthStateChanged(auth, (user) => {
if (!user) window.location.replace("login.html");
});
</script>
</body>
</html>