XTaylorSpenceX

Oracle Orbital Outpost

Sep 20th, 2025
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 29.84 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8"/>
  5. <meta name="viewport" content="width=device-width,initial-scale=1"/>
  6. <title>Oracle Orbital Outpost — Prophetic Colony Survival</title>
  7. <style>
  8. :root {
  9.   --space-black: #0a0614;
  10.   --deep-purple: #1a0f3a;
  11.   --oracle-glow: #9c4dc7;
  12.   --warning-orange: #ff8c42;
  13.   --danger-red: #ff3e41;
  14.   --safe-blue: #42a5ff;
  15.   --resource-green: #4cff88;
  16.   --text-white: #e8e3ff;
  17.   --panel-bg: rgba(20, 10, 40, 0.85);
  18. }
  19. * {
  20.   margin: 0;
  21.   padding: 0;
  22.   box-sizing: border-box;
  23. }
  24. body {
  25.   font-family: 'Courier New', monospace;
  26.   background: linear-gradient(180deg, var(--space-black) 0%, var(--deep-purple) 100%);
  27.   color: var(--text-white);
  28.   overflow: hidden;
  29.   height: 100vh;
  30.   position: relative;
  31. }
  32. #starfield {
  33.   position: absolute;
  34.   width: 100%;
  35.   height: 100%;
  36.   z-index: 1;
  37. }
  38. .star {
  39.   position: absolute;
  40.   background: white;
  41.   border-radius: 50%;
  42.   animation: twinkle 2s infinite;
  43. }
  44. @keyframes twinkle {
  45.   0%, 100% { opacity: 0.3; }
  46.   50% { opacity: 1; }
  47. }
  48. #gas-giant {
  49.   position: absolute;
  50.   left: 50%;
  51.   top: 50%;
  52.   transform: translate(-50%, -50%);
  53.   width: 400px;
  54.   height: 400px;
  55.   border-radius: 50%;
  56.   background: radial-gradient(circle at 30% 30%,
  57.     #7a3d8f 0%,
  58.     #4a2457 30%,
  59.     #2a1435 60%,
  60.     #150920 100%);
  61.   box-shadow:
  62.     0 0 80px var(--oracle-glow),
  63.     inset -20px -20px 40px rgba(0,0,0,0.5);
  64.   z-index: 5;
  65.   overflow: hidden;
  66. }
  67. .storm-band {
  68.   position: absolute;
  69.   width: 100%;
  70.   height: 60px;
  71.   background: linear-gradient(90deg,
  72.     transparent,
  73.     rgba(156, 77, 199, 0.3),
  74.     rgba(255, 140, 66, 0.2),
  75.     transparent);
  76.   animation: rotate-band 20s linear infinite;
  77. }
  78. .storm-band:nth-child(1) { top: 20%; animation-duration: 25s; }
  79. .storm-band:nth-child(2) { top: 40%; animation-duration: 18s; animation-direction: reverse; }
  80. .storm-band:nth-child(3) { top: 60%; animation-duration: 22s; }
  81. @keyframes rotate-band {
  82.   from { transform: translateX(-100%); }
  83.   to { transform: translateX(100%); }
  84. }
  85. .storm-eye {
  86.   position: absolute;
  87.   border-radius: 50%;
  88.   animation: pulse-storm 3s ease-in-out infinite;
  89. }
  90. @keyframes pulse-storm {
  91.   0%, 100% {
  92.     opacity: 0.6;
  93.     transform: scale(1);
  94.   }
  95.   50% {
  96.     opacity: 1;
  97.     transform: scale(1.2);
  98.   }
  99. }
  100. .orbital-object {
  101.   position: absolute;
  102.   left: 50%;
  103.   top: 15%;
  104.   transform: translateX(-50%);
  105.   width: 120px;
  106.   height: 40px;
  107.   background: linear-gradient(90deg, #444, #666, #444);
  108.   border: 2px solid var(--safe-blue);
  109.   border-radius: 20px;
  110.   z-index: 10;
  111.   animation: orbit 60s linear infinite;
  112.   transform-origin: center 250px;
  113.   cursor: pointer;
  114.   text-align: center;
  115.   line-height: 40px;
  116.   font-size: 12px;
  117. }
  118. @keyframes orbit {
  119.   from { transform: translateX(-50%) rotate(0deg) translateY(-250px); }
  120.   to { transform: translateX(-50%) rotate(360deg) translateY(-250px); }
  121. }
  122. #orbital-station {
  123.   border-color: var(--safe-blue);
  124. }
  125. #gravitas-ship {
  126.   border-color: var(--oracle-glow);
  127.   animation-delay: -15s;
  128. }
  129. #novos-ship {
  130.   border-color: var(--safe-blue);
  131.   animation-delay: -30s;
  132. }
  133. #spectrometer-ship {
  134.   border-color: var(--resource-green);
  135.   animation-delay: -45s;
  136. }
  137. .module {
  138.   position: absolute;
  139.   width: 20px;
  140.   height: 20px;
  141.   background: #888;
  142.   border: 1px solid var(--safe-blue);
  143.   border-radius: 4px;
  144. }
  145. #control-panel {
  146.   position: fixed;
  147.   top: 20px;
  148.   left: 20px;
  149.   width: 320px;
  150.   background: var(--panel-bg);
  151.   border: 2px solid var(--oracle-glow);
  152.   border-radius: 10px;
  153.   padding: 20px;
  154.   z-index: 100;
  155.   backdrop-filter: blur(10px);
  156. }
  157. #resource-panel {
  158.   position: fixed;
  159.   top: 20px;
  160.   right: 20px;
  161.   width: 280px;
  162.   background: var(--panel-bg);
  163.   border: 2px solid var(--safe-blue);
  164.   border-radius: 10px;
  165.   padding: 20px;
  166.   z-index: 100;
  167.   backdrop-filter: blur(10px);
  168. }
  169. #prophecy-panel {
  170.   position: fixed;
  171.   bottom: 20px;
  172.   left: 50%;
  173.   transform: translateX(-50%);
  174.   width: 600px;
  175.   max-width: 90vw;
  176.   background: var(--panel-bg);
  177.   border: 2px solid var(--warning-orange);
  178.   border-radius: 10px;
  179.   padding: 20px;
  180.   z-index: 100;
  181.   backdrop-filter: blur(10px);
  182. }
  183. .panel-title {
  184.   font-size: 18px;
  185.   font-weight: bold;
  186.   margin-bottom: 15px;
  187.   text-transform: uppercase;
  188.   letter-spacing: 2px;
  189.   color: var(--oracle-glow);
  190.   text-shadow: 0 0 10px currentColor;
  191. }
  192. .resource-item {
  193.   display: flex;
  194.   justify-content: space-between;
  195.   margin-bottom: 10px;
  196.   padding: 8px;
  197.   background: rgba(0,0,0,0.3);
  198.   border-radius: 5px;
  199.   border-left: 3px solid var(--resource-green);
  200. }
  201. .resource-value {
  202.   font-weight: bold;
  203.   color: var(--resource-green);
  204. }
  205. .storm-prediction {
  206.   background: rgba(0,0,0,0.4);
  207.   border-radius: 8px;
  208.   padding: 15px;
  209.   margin-bottom: 10px;
  210.   border-left: 4px solid var(--warning-orange);
  211.   position: relative;
  212.   overflow: hidden;
  213. }
  214. .storm-prediction::before {
  215.   content: '';
  216.   position: absolute;
  217.   top: 0;
  218.   left: 0;
  219.   width: 100%;
  220.   height: 100%;
  221.   background: linear-gradient(90deg, transparent, rgba(255,140,66,0.1), transparent);
  222.   animation: scan 3s linear infinite;
  223. }
  224. @keyframes scan {
  225.   from { transform: translateX(-100%); }
  226.   to { transform: translateX(100%); }
  227. }
  228. .prophecy-timer {
  229.   font-size: 24px;
  230.   font-weight: bold;
  231.   text-align: center;
  232.   margin: 10px 0;
  233.   color: var(--warning-orange);
  234.   text-shadow: 0 0 20px currentColor;
  235. }
  236. button {
  237.   background: linear-gradient(135deg, var(--oracle-glow), var(--deep-purple));
  238.   color: white;
  239.   border: none;
  240.   padding: 10px 20px;
  241.   margin: 5px;
  242.   border-radius: 5px;
  243.   cursor: pointer;
  244.   font-family: inherit;
  245.   font-weight: bold;
  246.   text-transform: uppercase;
  247.   transition: all 0.3s;
  248.   box-shadow: 0 4px 10px rgba(156, 77, 199, 0.4);
  249. }
  250. button:hover {
  251.   transform: translateY(-2px);
  252.   box-shadow: 0 6px 15px rgba(156, 77, 199, 0.6);
  253. }
  254. button:active {
  255.   transform: translateY(0);
  256. }
  257. button:disabled {
  258.   opacity: 0.5;
  259.   cursor: not-allowed;
  260.   transform: none;
  261. }
  262. .defense-grid {
  263.   display: grid;
  264.   grid-template-columns: repeat(2, 1fr);
  265.   gap: 10px;
  266.   margin-top: 15px;
  267. }
  268. .defense-item {
  269.   background: rgba(0,0,0,0.3);
  270.   padding: 10px;
  271.   border-radius: 5px;
  272.   border: 1px solid var(--safe-blue);
  273.   text-align: center;
  274. }
  275. .defense-level {
  276.   font-size: 20px;
  277.   font-weight: bold;
  278.   color: var(--safe-blue);
  279. }
  280. #event-log {
  281.   position: fixed;
  282.   bottom: 20px;
  283.   left: 20px;
  284.   width: 300px;
  285.   max-height: 200px;
  286.   overflow-y: auto;
  287.   background: var(--panel-bg);
  288.   border: 1px solid var(--oracle-glow);
  289.   border-radius: 5px;
  290.   padding: 10px;
  291.   z-index: 100;
  292.   font-size: 12px;
  293. }
  294. .log-entry {
  295.   margin-bottom: 5px;
  296.   padding: 5px;
  297.   border-left: 2px solid var(--safe-blue);
  298.   padding-left: 10px;
  299.   animation: fade-in 0.5s;
  300. }
  301. @keyframes fade-in {
  302.   from {
  303.     opacity: 0;
  304.     transform: translateX(-20px);
  305.   }
  306.   to {
  307.     opacity: 1;
  308.     transform: translateX(0);
  309.   }
  310. }
  311. .log-entry.warning { border-color: var(--warning-orange); }
  312. .log-entry.danger { border-color: var(--danger-red); }
  313. .log-entry.success { border-color: var(--resource-green); }
  314. #game-over {
  315.   display: none;
  316.   position: fixed;
  317.   top: 50%;
  318.   left: 50%;
  319.   transform: translate(-50%, -50%);
  320.   background: var(--panel-bg);
  321.   border: 3px solid var(--danger-red);
  322.   border-radius: 10px;
  323.   padding: 40px;
  324.   z-index: 1000;
  325.   text-align: center;
  326. }
  327. .glowing-text {
  328.   animation: glow 2s ease-in-out infinite;
  329. }
  330. @keyframes glow {
  331.   0%, 100% { text-shadow: 0 0 10px currentColor; }
  332.   50% { text-shadow: 0 0 20px currentColor, 0 0 30px currentColor; }
  333. }
  334. .hazard-indicator {
  335.   position: absolute;
  336.   width: 60px;
  337.   height: 60px;
  338.   border-radius: 50%;
  339.   pointer-events: none;
  340.   z-index: 50;
  341. }
  342. @keyframes asteroid-approach {
  343.   from {
  344.     transform: translate(-200%, -200%) scale(0.1);
  345.     opacity: 0;
  346.   }
  347.   to {
  348.     transform: translate(0, 0) scale(1);
  349.     opacity: 1;
  350.   }
  351. }
  352. @keyframes solar-flare {
  353.   0% {
  354.     box-shadow: 0 0 20px var(--warning-orange);
  355.     background: radial-gradient(circle, var(--warning-orange), transparent);
  356.   }
  357.   50% {
  358.     box-shadow: 0 0 40px var(--danger-red);
  359.     background: radial-gradient(circle, var(--danger-red), transparent);
  360.   }
  361.   100% {
  362.     box-shadow: 0 0 20px var(--warning-orange);
  363.     background: radial-gradient(circle, var(--warning-orange), transparent);
  364.   }
  365. }
  366. .cosmic-warning {
  367.   position: fixed;
  368.   top: 50%;
  369.   left: 50%;
  370.   transform: translate(-50%, -50%);
  371.   font-size: 48px;
  372.   font-weight: bold;
  373.   text-transform: uppercase;
  374.   color: var(--danger-red);
  375.   text-shadow: 0 0 30px currentColor;
  376.   animation: flash-warning 0.5s ease-in-out 3;
  377.   z-index: 200;
  378.   pointer-events: none;
  379. }
  380. @keyframes flash-warning {
  381.   0%, 100% { opacity: 0; }
  382.   50% { opacity: 1; }
  383. }
  384. #ship-menu {
  385.   display: none;
  386.   position: fixed;
  387.   top: 50%;
  388.   left: 50%;
  389.   transform: translate(-50%, -50%);
  390.   width: 400px;
  391.   background: var(--panel-bg);
  392.   border: 2px solid var(--safe-blue);
  393.   border-radius: 10px;
  394.   padding: 20px;
  395.   z-index: 1000;
  396.   backdrop-filter: blur(10px);
  397.   text-align: center;
  398. }
  399. .close {
  400.   position: absolute;
  401.   top: 10px;
  402.   right: 10px;
  403.   font-size: 30px;
  404.   cursor: pointer;
  405.   color: var(--text-white);
  406. }
  407. .ship-actions {
  408.   display: grid;
  409.   grid-template-columns: repeat(3, 1fr);
  410.   gap: 10px;
  411.   margin-top: 15px;
  412. }
  413. </style>
  414. </head>
  415. <body>
  416. <canvas id="starfield"></canvas>
  417. <div id="gas-giant">
  418.   <div class="storm-band"></div>
  419.   <div class="storm-band"></div>
  420.   <div class="storm-band"></div>
  421. </div>
  422. <div id="orbital-station" class="orbital-object">
  423.   <div class="module" style="top: -10px; left: 10px;"></div>
  424.   <div class="module" style="top: -10px; right: 10px;"></div>
  425.   <div class="module" style="bottom: -10px; left: 30px;"></div>
  426.   <div class="module" style="bottom: -10px; right: 30px;"></div>
  427. </div>
  428. <div id="gravitas-ship" class="orbital-object" onclick="game.openShipMenu('gravitas')">Gravitas</div>
  429. <div id="novos-ship" class="orbital-object" onclick="game.openShipMenu('novos')">Novos</div>
  430. <div id="spectrometer-ship" class="orbital-object" onclick="game.openShipMenu('spectrometer')">Spectrometer</div>
  431. <div id="control-panel">
  432.   <div class="panel-title glowing-text">Colony Command</div>
  433.   <div>Population: <span id="population">1000</span></div>
  434.   <div>Day: <span id="day">1</span></div>
  435.   <div>Status: <span id="status">Monitoring</span></div>
  436.  
  437.   <div class="defense-grid">
  438.     <div class="defense-item">
  439.       <div>Shields</div>
  440.       <div class="defense-level" id="shield-level">0</div>
  441.       <button onclick="game.upgradeDefense('shields')">Upgrade (50)</button>
  442.     </div>
  443.     <div class="defense-item">
  444.       <div>Lasers</div>
  445.       <div class="defense-level" id="laser-level">0</div>
  446.       <button onclick="game.upgradeDefense('lasers')">Upgrade (40)</button>
  447.     </div>
  448.     <div class="defense-item">
  449.       <div>Hull</div>
  450.       <div class="defense-level" id="hull-level">0</div>
  451.       <button onclick="game.upgradeDefense('hull')">Upgrade (30)</button>
  452.     </div>
  453.     <div class="defense-item">
  454.       <div>Scanner</div>
  455.       <div class="defense-level" id="scanner-level">0</div>
  456.       <button onclick="game.upgradeDefense('scanner')">Upgrade (60)</button>
  457.     </div>
  458.   </div>
  459. </div>
  460. <div id="resource-panel">
  461.   <div class="panel-title">Resources</div>
  462.   <div class="resource-item">
  463.     <span>Energy</span>
  464.     <span class="resource-value" id="energy">100</span>
  465.   </div>
  466.   <div class="resource-item">
  467.     <span>Materials</span>
  468.     <span class="resource-value" id="materials">100</span>
  469.   </div>
  470.   <div class="resource-item">
  471.     <span>Food</span>
  472.     <span class="resource-value" id="food">100</span>
  473.   </div>
  474.   <div class="resource-item">
  475.     <span>Morale</span>
  476.     <span class="resource-value" id="morale">100</span>
  477.   </div>
  478. </div>
  479. <div id="prophecy-panel">
  480.   <div class="panel-title">Oracle Readings</div>
  481.   <div id="prophecy-content">
  482.     <div class="storm-prediction">
  483.       The storms are calm... for now.
  484.     </div>
  485.   </div>
  486.   <div class="prophecy-timer" id="next-event">Next Reading: <span id="timer">30</span>s</div>
  487. </div>
  488. <div id="event-log"></div>
  489. <div id="game-over">
  490.   <h2 style="color: var(--danger-red);">Colony Lost</h2>
  491.   <p id="game-over-reason"></p>
  492.   <p>Survived <span id="days-survived">0</span> days</p>
  493.   <button onclick="location.reload()">Try Again</button>
  494. </div>
  495. <div id="ship-menu">
  496.   <span class="close" onclick="game.closeShipMenu()">&times;</span>
  497.   <div class="panel-title">Friendly Ship Options Menu</div>
  498.   <p id="ship-desc"></p>
  499.   <div class="ship-actions">
  500.     <button onclick="game.shipAction(game.currentShip, 'trade')">Trade</button>
  501.     <button onclick="game.shipAction(game.currentShip, 'boostMorale')">Boost Morale</button>
  502.     <button onclick="game.shipAction(game.currentShip, 'getResources')">Receive Resources</button>
  503.     <button onclick="game.shipAction(game.currentShip, 'quest')">Quest</button>
  504.     <button onclick="game.shipAction(game.currentShip, 'explore')">Explore</button>
  505.     <button onclick="game.shipAction(game.currentShip, 'devour')">Devour</button>
  506.     <button onclick="game.shipAction(game.currentShip, 'destroy')">Destroy</button>
  507.     <button onclick="game.shipAction(game.currentShip, 'fight')">Fight</button>
  508.     <button onclick="game.shipAction(game.currentShip, 'assimilate')">Assimilate</button>
  509.     <!-- Add more playful actions if desired, but core ones implemented -->
  510.   </div>
  511. </div>
  512. <script>
  513. const game = {
  514.   population: 1000,
  515.   day: 1,
  516.   resources: {
  517.     energy: 100,
  518.     materials: 100,
  519.     food: 100,
  520.     morale: 100
  521.   },
  522.   defenses: {
  523.     shields: 0,
  524.     lasers: 0,
  525.     hull: 0,
  526.     scanner: 0
  527.   },
  528.   allyCooldowns: {
  529.     gravitas: 0,
  530.     novos: 0,
  531.     spectrometer: 0
  532.   },
  533.   currentShip: null,
  534.   nextEvent: null,
  535.   eventTimer: 30,
  536.   currentProphecy: null,
  537.   isGameOver: false,
  538.  
  539.   hazardTypes: {
  540.     asteroids: {
  541.       name: 'Asteroid Swarm',
  542.       damage: { hull: 40, population: 50 },
  543.       defense: 'lasers',
  544.       stormPattern: 'spiraling vortex',
  545.       stormColor: '#ff8c42',
  546.       warning: 'Rocky debris detected in the storms!'
  547.     },
  548.     solarFlare: {
  549.       name: 'Solar Flare',
  550.       damage: { energy: 60, shields: 30, morale: 40 },
  551.       defense: 'shields',
  552.       stormPattern: 'bright eruptions',
  553.       stormColor: '#ffdd00',
  554.       warning: 'The storms glow with unnatural light!'
  555.     },
  556.     pirates: {
  557.       name: 'Pirate Raid',
  558.       damage: { materials: 50, food: 40, population: 30 },
  559.       defense: 'lasers',
  560.       stormPattern: 'dark shadows',
  561.       stormColor: '#ff3e41',
  562.       warning: 'Sinister shapes lurk within the clouds!'
  563.     },
  564.     cosmicStorm: {
  565.       name: 'Cosmic Storm',
  566.       damage: { energy: 40, morale: 50, shields: 20 },
  567.       defense: 'shields',
  568.       stormPattern: 'electric tendrils',
  569.       stormColor: '#9c4dc7',
  570.       warning: 'The storms crackle with otherworldly energy!'
  571.     },
  572.     void: {
  573.       name: 'Void Anomaly',
  574.       damage: { morale: 70, food: 30 },
  575.       defense: 'scanner',
  576.       stormPattern: 'empty darkness',
  577.       stormColor: '#1a0f3a',
  578.       warning: 'The storms reveal an ominous void!'
  579.     }
  580.   },
  581.  
  582.   init() {
  583.     this.createStarfield();
  584.     this.updateDisplay();
  585.     this.startGameLoop();
  586.     this.addLog('Colony established in orbit of the Oracle Giant', 'success');
  587.     this.generateProphecy();
  588.     document.addEventListener('keydown', (e) => {
  589.       if (e.key === 'Escape') this.closeShipMenu();
  590.     });
  591.   },
  592.  
  593.   createStarfield() {
  594.     const canvas = document.getElementById('starfield');
  595.     const ctx = canvas.getContext('2d');
  596.     canvas.width = window.innerWidth;
  597.     canvas.height = window.innerHeight;
  598.    
  599.     for (let i = 0; i < 200; i++) {
  600.      const star = document.createElement('div');
  601.      star.className = 'star';
  602.      star.style.left = Math.random() * 100 + '%';
  603.      star.style.top = Math.random() * 100 + '%';
  604.      star.style.width = star.style.height = Math.random() * 3 + 'px';
  605.      star.style.animationDelay = Math.random() * 2 + 's';
  606.      document.body.appendChild(star);
  607.    }
  608.  },
  609.  
  610.  startGameLoop() {
  611.    setInterval(() => {
  612.       if (this.isGameOver) return;
  613.      
  614.       this.eventTimer--;
  615.       document.getElementById('timer').textContent = this.eventTimer;
  616.      
  617.       if (this.eventTimer <= 0) {
  618.        if (this.currentProphecy) {
  619.          this.executeHazard(this.currentProphecy);
  620.        }
  621.        this.generateProphecy();
  622.        this.eventTimer = 25 + Math.floor(Math.random() * 15);
  623.      }
  624.    
  625.      // Resource generation and ally cooldowns
  626.      if (this.eventTimer % 5 === 0) {
  627.        this.resources.energy += 2 + this.defenses.scanner;
  628.        this.resources.materials += 1;
  629.        this.resources.food -= Math.floor(this.population / 200);
  630.        this.resources.morale += this.defenses.hull > 3 ? 1 : 0;
  631.        
  632.         this.checkResourceLimits();
  633.         this.updateDisplay();
  634.  
  635.         // Automatic ally events
  636.         if (Math.random() < 0.02) {
  637.          const ships = ['gravitas', 'novos', 'spectrometer'];
  638.          const ship = ships[Math.floor(Math.random() * 3)];
  639.          const giftType = Math.floor(Math.random() * 4);
  640.          if (giftType === 0) {
  641.            this.resources.morale += 5;
  642.            this.addLog(`${ship.charAt(0).toUpperCase() + ship.slice(1)} sent encouraging messages! +5 morale`, 'success');
  643.          } else if (giftType === 1) {
  644.            this.resources.food += 10;
  645.            this.addLog(`${ship.charAt(0).toUpperCase() + ship.slice(1)} traded surplus food! +10 food`, 'success');
  646.          } else if (giftType === 2) {
  647.            this.resources.energy += 15;
  648.            this.addLog(`${ship.charAt(0).toUpperCase() + ship.slice(1)} shared energy cells! +15 energy`, 'success');
  649.          } else {
  650.            this.population += 10;
  651.            this.addLog(`${ship.charAt(0).toUpperCase() + ship.slice(1)} transferred crew members! +10 population`, 'success');
  652.          }
  653.          this.updateDisplay();
  654.        }
  655.      }
  656.  
  657.      // Decrement ally cooldowns
  658.      for (let ship in this.allyCooldowns) {
  659.        if (this.allyCooldowns[ship] > 0) this.allyCooldowns[ship]--;
  660.       }
  661.     }, 1000);
  662.    
  663.     // Day cycle
  664.     setInterval(() => {
  665.       if (!this.isGameOver) {
  666.         this.day++;
  667.         this.updateDisplay();
  668.         this.addLog(`Day ${this.day} begins`, 'success');
  669.       }
  670.     }, 60000);
  671.   },
  672.  
  673.   generateProphecy() {
  674.     const hazardKeys = Object.keys(this.hazardTypes);
  675.     const hazardType = hazardKeys[Math.floor(Math.random() * hazardKeys.length)];
  676.     const hazard = this.hazardTypes[hazardType];
  677.    
  678.     this.currentProphecy = hazardType;
  679.    
  680.     // Show storm patterns
  681.     this.showStormPattern(hazard);
  682.    
  683.     // Update prophecy panel
  684.     const prophecyContent = document.getElementById('prophecy-content');
  685.     prophecyContent.innerHTML = `
  686.       <div class="storm-prediction">
  687.         <strong>The Oracle speaks:</strong><br>
  688.         "${hazard.warning}"<br><br>
  689.         <em>Storm pattern: ${hazard.stormPattern}</em><br>
  690.         <small>Recommended defense: ${hazard.defense.toUpperCase()}</small>
  691.       </div>
  692.     `;
  693.    
  694.     this.addLog(`New prophecy: ${hazard.stormPattern} detected`, 'warning');
  695.   },
  696.  
  697.   showStormPattern(hazard) {
  698.     const giant = document.getElementById('gas-giant');
  699.    
  700.     // Add storm eyes
  701.     for (let i = 0; i < 3; i++) {
  702.      const eye = document.createElement('div');
  703.      eye.className = 'storm-eye';
  704.      eye.style.width = '40px';
  705.      eye.style.height = '40px';
  706.      eye.style.background = `radial-gradient(circle, ${hazard.stormColor}, transparent)`;
  707.      eye.style.left = Math.random() * 80 + 10 + '%';
  708.      eye.style.top = Math.random() * 80 + 10 + '%';
  709.      eye.style.animationDelay = i * 0.3 + 's';
  710.      giant.appendChild(eye);
  711.    
  712.      setTimeout(() => eye.remove(), 10000);
  713.     }
  714.   },
  715.  
  716.   executeHazard(hazardType) {
  717.     const hazard = this.hazardTypes[hazardType];
  718.    
  719.     // Show warning
  720.     const warning = document.createElement('div');
  721.     warning.className = 'cosmic-warning';
  722.     warning.textContent = hazard.name + ' INCOMING!';
  723.     document.body.appendChild(warning);
  724.     setTimeout(() => warning.remove(), 1500);
  725.    
  726.     // Calculate damage reduction from defenses
  727.     const defenseLevel = this.defenses[hazard.defense];
  728.     const reduction = defenseLevel * 0.15; // 15% reduction per level
  729.    
  730.     // Apply damage
  731.     let totalDamage = 0;
  732.     for (const [resource, damage] of Object.entries(hazard.damage)) {
  733.       const actualDamage = Math.floor(damage * (1 - reduction));
  734.      
  735.       if (resource === 'population') {
  736.         this.population = Math.max(0, this.population - actualDamage);
  737.       } else if (this.resources[resource] !== undefined) {
  738.         if (resource === 'morale') {
  739.           const reducedMoraleDamage = Math.floor(actualDamage * 0.17);
  740.           this.resources[resource] = Math.max(0, this.resources[resource] - reducedMoraleDamage);
  741.           totalDamage += reducedMoraleDamage;
  742.         } else {
  743.           this.resources[resource] = Math.max(0, this.resources[resource] - actualDamage);
  744.           totalDamage += actualDamage;
  745.         }
  746.       } else if (this.defenses[resource] !== undefined) {
  747.         this.defenses[resource] = Math.max(0, this.defenses[resource] - 1);
  748.       }
  749.      
  750.     }
  751.    
  752.     // Add visual effect
  753.     this.createHazardVisual(hazardType);
  754.    
  755.     // Log event
  756.     const message = defenseLevel > 0
  757.       ? `${hazard.name} hit! Defenses reduced damage by ${Math.floor(reduction * 100)}%`
  758.       : `${hazard.name} hit with full force!`;
  759.     this.addLog(message, 'danger');
  760.    
  761.     // Check game over
  762.     this.checkGameOver();
  763.     this.updateDisplay();
  764.   },
  765.  
  766.   createHazardVisual(hazardType) {
  767.     const hazard = this.hazardTypes[hazardType];
  768.    
  769.     if (hazardType === 'asteroids') {
  770.       for (let i = 0; i < 5; i++) {
  771.        setTimeout(() => {
  772.           const asteroid = document.createElement('div');
  773.           asteroid.className = 'hazard-indicator';
  774.           asteroid.style.background = 'radial-gradient(circle, #8B4513, #654321)';
  775.           asteroid.style.left = Math.random() * window.innerWidth + 'px';
  776.           asteroid.style.top = Math.random() * window.innerHeight + 'px';
  777.           asteroid.style.animation = 'asteroid-approach 2s ease-in';
  778.           document.body.appendChild(asteroid);
  779.           setTimeout(() => asteroid.remove(), 2000);
  780.         }, i * 200);
  781.       }
  782.     } else if (hazardType === 'solarFlare') {
  783.       const flare = document.createElement('div');
  784.       flare.style.position = 'fixed';
  785.       flare.style.top = '0';
  786.       flare.style.left = '0';
  787.       flare.style.width = '100%';
  788.       flare.style.height = '100%';
  789.       flare.style.background = `radial-gradient(circle at center, ${hazard.stormColor}44, transparent)`;
  790.       flare.style.animation = 'solar-flare 2s';
  791.       flare.style.zIndex = '500';
  792.       flare.style.pointerEvents = 'none';
  793.       document.body.appendChild(flare);
  794.       setTimeout(() => flare.remove(), 2000);
  795.     }
  796.   },
  797.  
  798.   upgradeDefense(type) {
  799.     const costs = {
  800.       shields: 50,
  801.       lasers: 40,
  802.       hull: 30,
  803.       scanner: 60
  804.     };
  805.    
  806.     const cost = costs[type];
  807.     if (this.resources.materials >= cost) {
  808.       this.resources.materials -= cost;
  809.       this.defenses[type]++;
  810.       this.updateDisplay();
  811.       this.addLog(`${type.charAt(0).toUpperCase() + type.slice(1)} upgraded to level ${this.defenses[type]}`, 'success');
  812.      
  813.       // Special effects for scanner
  814.       if (type === 'scanner' && this.defenses.scanner > 2) {
  815.        this.eventTimer += 5;
  816.         this.addLog('Advanced scanners provide more warning time!', 'success');
  817.       }
  818.     } else {
  819.       this.addLog('Insufficient materials!', 'danger');
  820.     }
  821.   },
  822.  
  823.   openShipMenu(ship) {
  824.     this.currentShip = ship;
  825.     document.getElementById('ship-menu').style.display = 'block';
  826.     let desc = '';
  827.     if (ship === 'gravitas') desc = 'Representing the Gravitas Organization - Masters of cosmic gravity and stability.';
  828.     else if (ship === 'novos') desc = 'Representing the Novos Organization - Pioneers of innovation and renewal.';
  829.     else if (ship === 'spectrometer') desc = 'Representing the Spectrometer Organization - Experts in analysis and spectral insights.';
  830.     document.getElementById('ship-desc').textContent = desc;
  831.   },
  832.  
  833.   closeShipMenu() {
  834.     document.getElementById('ship-menu').style.display = 'none';
  835.     this.currentShip = null;
  836.   },
  837.  
  838.   shipAction(ship, action) {
  839.     if (this.allyCooldowns[ship] > 0) {
  840.       this.addLog(`${ship.charAt(0).toUpperCase() + ship.slice(1)} is on cooldown! Wait ${this.allyCooldowns[ship]}s.`, 'warning');
  841.       return;
  842.     }
  843.     let success = true;
  844.     switch (action) {
  845.       case 'trade':
  846.         if (this.resources.materials >= 20) {
  847.           this.resources.materials -= 20;
  848.           this.resources.energy += 30;
  849.           this.addLog(`Traded with ${ship.charAt(0).toUpperCase() + ship.slice(1)}: -20 materials, +30 energy`, 'success');
  850.         } else {
  851.           this.addLog('Not enough materials for trade!', 'danger');
  852.           success = false;
  853.         }
  854.         break;
  855.       case 'boostMorale':
  856.         this.resources.morale += 15;
  857.         this.addLog(`${ship.charAt(0).toUpperCase() + ship.slice(1)} boosted colony morale by 15!`, 'success');
  858.         break;
  859.       case 'getResources':
  860.         this.resources.food += 10;
  861.         this.resources.materials += 5;
  862.         this.addLog(`${ship.charAt(0).toUpperCase() + ship.slice(1)} gifted free resources: +10 food, +5 materials`, 'success');
  863.         break;
  864.       case 'quest':
  865.         this.resources.morale += 10;
  866.         this.resources.energy -= 5;
  867.         this.addLog(`${ship.charAt(0).toUpperCase() + ship.slice(1)} offered a quest: +10 morale, -5 energy`, 'success');
  868.         break;
  869.       case 'explore':
  870.         this.resources.materials += 15;
  871.         this.addLog(`${ship.charAt(0).toUpperCase() + ship.slice(1)} shared exploration findings: +15 materials`, 'success');
  872.         break;
  873.       case 'devour':
  874.         this.resources.energy += 50;
  875.         this.population -= 20;
  876.         this.addLog(`You devoured ${ship.charAt(0).toUpperCase() + ship.slice(1)}: +50 energy, but -20 population!`, 'danger');
  877.         document.getElementById(`${ship}-ship`).style.display = 'none'; // Remove ship
  878.         break;
  879.       case 'destroy':
  880.         this.resources.materials += 30;
  881.         this.resources.morale -= 30;
  882.         this.addLog(`Destroyed ${ship.charAt(0).toUpperCase() + ship.slice(1)}: +30 materials, -30 morale`, 'danger');
  883.         document.getElementById(`${ship}-ship`).style.display = 'none';
  884.         break;
  885.       case 'fight':
  886.         const damage = Math.random() > 0.5 ? 20 : -20;
  887.         this.resources.energy += damage;
  888.         this.addLog(`Fought ${ship.charAt(0).toUpperCase() + ship.slice(1)}: ${damage > 0 ? '+' : ''}${damage} energy`, damage > 0 ? 'success' : 'danger');
  889.         break;
  890.       case 'assimilate':
  891.         this.population += 50;
  892.         this.resources.morale -= 10;
  893.         this.addLog(`Assimilated crew from ${ship.charAt(0).toUpperCase() + ship.slice(1)}: +50 population, -10 morale`, 'success');
  894.         break;
  895.       default:
  896.         this.addLog(`Action '${action}' with ${ship.charAt(0).toUpperCase() + ship.slice(1)} echoes mysteriously...`, 'warning');
  897.         success = false;
  898.         break;
  899.     }
  900.     if (success) {
  901.       this.allyCooldowns[ship] = 30; // 30 seconds cooldown
  902.     }
  903.     this.updateDisplay();
  904.   },
  905.  
  906.   checkResourceLimits() {
  907.     for (const resource in this.resources) {
  908.       this.resources[resource] = Math.max(0, Math.min(200, this.resources[resource]));
  909.     }
  910.    
  911.     // Morale affects productivity (reduced to 17% rate via probability)
  912.     if (this.resources.morale < 30) {
  913.      if (Math.random() < 0.17) this.resources.energy -= 1;
  914.      if (Math.random() < 0.17) this.resources.materials -= 1;
  915.    }
  916.  
  917.    // Starvation
  918.    if (this.resources.food <= 0) {
  919.      this.population -= 10;
  920.      this.resources.morale -= 5;
  921.    }
  922.  },
  923.  
  924.  checkGameOver() {
  925.    if (this.population <= 0) {
  926.      this.gameOver('Population extinct');
  927.    } else if (this.resources.morale <= 0) {
  928.      this.gameOver('Colony rebellion - morale collapsed');
  929.    } else if (this.resources.energy <= 0 && this.resources.food <= 0) {
  930.      this.gameOver('Life support failure');
  931.    }
  932.  },
  933.  
  934.  gameOver(reason) {
  935.    this.isGameOver = true;
  936.    document.getElementById('game-over').style.display = 'block';
  937.    document.getElementById('game-over-reason').textContent = reason;
  938.    document.getElementById('days-survived').textContent = this.day;
  939.    this.addLog('GAME OVER: ' + reason, 'danger');
  940.  },
  941.  
  942.  updateDisplay() {
  943.    document.getElementById('population').textContent = this.population;
  944.    document.getElementById('day').textContent = this.day;
  945.    document.getElementById('status').textContent = this.eventTimer < 10 ? 'DANGER' : 'Monitoring';
  946.  
  947.    for (const resource in this.resources) {
  948.      const element = document.getElementById(resource);
  949.      if (element) {
  950.        element.textContent = this.resources[resource];
  951.        element.style.color = this.resources[resource] < 30 ? 'var(--danger-red)' : 'var(--resource-green)';
  952.      }
  953.    }
  954.  
  955.    for (const defense in this.defenses) {
  956.      const elementId = defense === 'lasers' ? 'laser-level' :
  957.                       defense === 'shields' ? 'shield-level' :
  958.                       defense === 'hull' ? 'hull-level' : 'scanner-level';
  959.      document.getElementById(elementId).textContent = this.defenses[defense];
  960.    }
  961.  },
  962.  
  963.  addLog(message, type = '') {
  964.    const log = document.getElementById('event-log');
  965.    const entry = document.createElement('div');
  966.    entry.className = 'log-entry ' + type;
  967.    entry.textContent = `[Day ${this.day}] ${message}`;
  968.    log.insertBefore(entry, log.firstChild);
  969.  
  970.    // Keep only last 10 entries
  971.    while (log.children.length > 10) {
  972.       log.removeChild(log.lastChild);
  973.     }
  974.   }
  975. };
  976. // Initialize game
  977. window.onload = () => game.init();
  978. </script>
  979. </body>
  980. </html>
  981.  
Advertisement
Add Comment
Please, Sign In to add comment