A Darkroom by doublespeakgames

  1. <!DOCTYPE html>
  2. <html itemscope itemtype="https://schema.org/CreativeWork">
  3. <head>
  4. <meta charset="UTF-8"/>
  5. <!--
  6. A Dark Room (v1.4)
  7. ==================
  8.  
  9. A minimalist text adventure by Michael Townsend and all his friends.
  10. Inspired by Candy Box (http://candies.aniwey.net/)
  11. Contribute on GitHub! (https://github.com/doublespeakgames/adarkroom/)
  12. -->
  13. <title>A Dark Room</title>
  14. <meta itemprop="description" name="description" property="og:description" content="A minimalist text adventure">
  15. <meta itemprop="image" property="og:image" content="img/adr.png" />
  16. <meta itemprop="name" property="og:title" content="A Dark Room" />
  17. <link rel="shortcut icon" href="favicon.ico" />
  18. <link rel="image_src" href="img/adr.png" />
  19. <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
  20. <script src="https://www.dropbox.com/static/api/dropbox-datastores-1.1-latest.js" type="text/javascript"></script>
  21. <script>
  22. if(!window.jQuery) {
  23. document.write('<script src="lib/jquery.min.js"><\/script>')
  24. }
  25. </script>
  26. <script src="lib/jquery.color-2.1.2.min.js"></script>
  27. <script src="lib/jquery.event.move.js"></script>
  28. <script src="lib/jquery.event.swipe.js"></script>
  29. <script src="lib/base64.js"></script>
  30. <script src="lib/translate.js"></script>
  31.  
  32. <script src="lang/langs.js"></script>
  33.  
  34. <script>
  35. // try to read "lang" param's from url
  36. var lang = decodeURIComponent((new RegExp('[?|&]lang=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null;
  37. // if no language requested, try to read it from local storage
  38. if(!lang){
  39. try {
  40. lang = localStorage.lang;
  41. } catch(e) {}
  42. }
  43. // if a language different than english requested, load all translations
  44. if(lang && lang != 'en'){
  45. document.write('<script src="lang/'+lang+'/strings.js"><\/script>');
  46. document.write('<link rel="stylesheet" type="text/css" href="lang/'+lang+'/main.css" \/>');
  47. }
  48. </script>
  49.  
  50. <script src="script/Button.js"></script>
  51. <script src="script/engine.js"></script>
  52. <script src="script/state_manager.js"></script>
  53. <script src="script/header.js"></script>
  54. <script src="script/notifications.js"></script>
  55. <script src="script/events.js"></script>
  56. <script src="script/dropbox.js"></script>
  57. <script src="script/room.js"></script>
  58. <script src="script/outside.js"></script>
  59. <script src="script/world.js"></script>
  60. <script src="script/path.js"></script>
  61. <script src="script/ship.js"></script>
  62. <script src="script/space.js"></script>
  63. <script src="script/prestige.js"></script>
  64. <script src="script/scoring.js"></script>
  65. <!-- Event modules -->
  66. <script src="script/events/global.js"></script>
  67. <script src="script/events/room.js"></script>
  68. <script src="script/events/outside.js"></script>
  69. <script src="script/events/encounters.js"></script>
  70. <script src="script/events/setpieces.js"></script>
  71.  
  72. <script type='text/javascript'>
  73. var oldIE = false;
  74. </script>
  75. <!--[if lt IE 9]>
  76. <script type="text/javascript">oldIE = true;</script>
  77. <![endif]-->
  78.  
  79. <link rel="stylesheet" type="text/css" href="css/main.css" />
  80. <link rel="stylesheet" type="text/css" href="css/room.css" />
  81. <link rel="stylesheet" type="text/css" href="css/outside.css" />
  82. <link rel="stylesheet" type="text/css" href="css/path.css" />
  83. <link rel="stylesheet" type="text/css" href="css/world.css" />
  84. <link rel="stylesheet" type="text/css" href="css/ship.css" />
  85. <link rel="stylesheet" type="text/css" href="css/space.css" />
  86.  
  87. <script src="script/localization.js"></script>
  88. <!-- Google Analytics -->
  89. <script>
  90. (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  91. (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  92. m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  93. })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
  94. ga('create', 'UA-41314886-1', 'doublespeakgames.com');
  95. ga('send', 'pageview');
  96. </script>
  97.  
  98. </head>
  99. <body>
  100. <div id="wrapper">
  101. <div id="saveNotify"><script>document.write(_("saved."));</script></div>
  102. <div id="content">
  103. <div id="outerSlider">
  104. <div id="main">
  105. <div id="header"></div>
  106. </div>
  107. </div>
  108. </div>
  109. </div>
  110. </body>
  111. </html>

Source Code

Shellshock.io

  1. !DOCTYPE html>
  2. <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1">
  6.  
  7. <!-- Styles & Fonts -->
  8. <link href="https://fonts.googleapis.com/css?family=Sigmar+One|Nunito:100,200,600,700,900" rel="stylesheet">
  9. <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
  10. <link rel="stylesheet" href="styles/transitions.css?1566102874">
  11. <link rel="stylesheet" href="styles/forms.css?1566102874">
  12. <link rel="stylesheet" href="styles/style.css?1566102874">
  13. <link rel="stylesheet" href="styles/game.css?1566102874">
  14.  
  15. <style>
  16. .eggIcon {
  17. display: inline-block;
  18. color: #444444;
  19. width: 1em;
  20. height: 1em;
  21. fill: currentColor;
  22. }
  23. </style>
  24.  
  25. <svg style="position: absolute; width: 0; height: 0; overflow: hidden" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  26. <defs>
  27. <symbol id="icon-egg" viewBox="0 0 14.59 18.12">
  28. <path class="eggFill" d="M14.49,10.79c0-3.96-3.02-10.66-6.98-10.66s-7.36,6.7-7.36,10.66s3.21,7.17,7.17,7.17S14.49,14.75,14.49,10.79z"></path>
  29. </symbol>
  30. </defs>
  31. </svg>
  32.  
  33. <style>
  34. .eggIconLocked {
  35. display: inline-block;
  36. color: #444444;
  37. width: 1em;
  38. height: 1em;
  39. fill: currentColor;
  40. }
  41. </style>
  42.  
  43. <svg style="position: absolute; width: 0; height: 0; overflow: hidden" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  44. <defs>
  45. <symbol id="icon-egg-locked" viewBox="0 0 14.59 18.12">
  46. <g>
  47. <path class="st0" d="M7.3,5.4c-0.6,0-1.1,0.5-1.1,1.1v1.3h2.2V6.5C8.4,5.9,7.9,5.4,7.3,5.4z"/>
  48. <path class="st0" d="M7.5,0.1c-4,0-7.4,6.7-7.4,10.7S3.4,18,7.3,18c3.9,0,7.2-3.2,7.2-7.2S11.5,0.1,7.5,0.1z M11.3,12.5
  49. c0,0.9-0.7,1.6-1.6,1.6H4.8c-0.9,0-1.6-0.7-1.6-1.6V7.8h1.5V6.5C4.8,5.1,5.9,4,7.3,4c1.4,0,2.5,1.1,2.5,2.5v1.3h1.5V12.5z"/>
  50. </g>
  51. </symbol>
  52. </defs>
  53. </svg>
  54. <!-- European Union detection -->
  55. <script>isFromEU = 0 ? true : false</script>
  56.  
  57. <!-- AdInPlay -->
  58. <meta name="viewport" content="minimal-ui, user-scalable=no, initial-scale=1, maximum-scale=1, width=device-width" />
  59. <script async src="//api.adinplay.com/libs/aiptag/pub/SSK/shellshock.io/tag.min.js"></script>
  60. <script>
  61. var aiptag = aiptag || {};
  62. aiptag.cmd = aiptag.cmd || [];
  63. aiptag.cmd.display = aiptag.cmd.display || [];
  64. aiptag.cmd.player = aiptag.cmd.player || [];
  65. </script>
  66.  
  67. <!-- Google AdManager -->
  68. <script>
  69. var useAdManager = false;
  70. console.log('Using GoogleAdManager: ' + useAdManager);
  71. console.log(useAdManager);
  72. </script>
  73.  
  74. <!-- Firebase -->
  75. <script src="https://www.gstatic.com/firebasejs/6.0.2/firebase-app.js"></script>
  76. <script src="https://www.gstatic.com/firebasejs/6.0.2/firebase-auth.js"></script>
  77.  
  78. <script src="https://cdn.firebase.com/libs/firebaseui/4.0.0/firebaseui.js"></script>
  79. <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/4.0.0/firebaseui.css" />
  80.  
  81. <!-- Facebook -->
  82. <!-- Facebook Pixel Code -->
  83. <script>
  84. !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
  85. n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
  86. n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
  87. t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
  88. document,'script','https://connect.facebook.net/en_US/fbevents.js');
  89. fbq('init', '771186996377132');
  90. fbq('track', 'PageView');
  91. </script>
  92. <noscript>
  93. <img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=771186996377132&ev=PageView&noscript=1"/>
  94. </noscript>
  95. <!-- DO NOT MODIFY -->
  96. <!-- End Facebook Pixel Code -->
  97.  
  98. <!-- ParsedURL -->
  99. <script>
  100. var parsedUrl = (function parseUrl () {
  101. var url = {};
  102. var loc = window.location;
  103. url.root = loc.origin + loc.pathname;
  104. var query = loc.search.substring(1).split('&');
  105. url.query = {};
  106. for (var i in query) {
  107. var arr = query[i].split('=');
  108. if (arr[0]) {
  109. if (arr[1] === undefined) {
  110. arr[1] = true;
  111. } else if (!isNaN(arr[1])) {
  112. arr[1] = parseFloat(arr[1]);
  113. }
  114. url.query[arr[0]] = arr[1];
  115. }
  116. }
  117. url.hash = loc.hash.substring(1);
  118. if (url.hash.length == 0) url.hash = undefined;
  119. return url;
  120. })();
  121. </script>
  122.  
  123. <!-- OneSignal -->
  124. <script src="https://cdn.onesignal.com/sdks/OneSignalSDK.js" async=""></script>
  125. <script>
  126. var osAppId = 'dae68bc6-167c-4012-8644-90fe9db39950';
  127.  
  128. if (!location.hostname.startsWith('shellshock')) {
  129. if (location.hostname.startsWith('localshelldev')) {
  130. osAppId = 'e515714b-808e-4800-a9e0-04633ec900b5'; // local testing
  131. } else if (location.hostname.startsWith('dev')) {
  132. osAppId = '20bd47ca-cce1-428e-b34f-1a240f643112'; // dev testing
  133. } else {
  134. osAppId = '166e17cb-5c02-4c7d-8bff-8ec69729f725'; // internal testing
  135. }
  136. }
  137.  
  138. var OneSignal = window.OneSignal || [];
  139. OneSignal.push(function() {
  140. OneSignal.init({
  141. appId: osAppId,
  142. });
  143. });
  144. </script>
  145. <!-- VueJS -->
  146. <script src="./js/vue/vue.min.2.6.10.js"></script>
  147.  
  148. <title>Shell Shockers | by Blue Wizard Digital</title>
  149. <meta name="Description" content="Welcome to Shell Shockers, the world's most advanced egg-based multiplayer shooter! It's like your favorite battlefield game but... with eggs.">
  150. <meta name="Keywords" content="Play, Free, Online, Multiplayer, Games, IO, ShellShockers, Shooter, Bullets, Top Down">
  151. <meta name="author" content="Blue Wizard Digital">
  152.  
  153. <link rel="icon" href="favicon.ico" type="image/x-icon">
  154. <meta property="og:url" content="https://www.shellshock.io" />
  155. <meta property="og:type" content="website" />
  156. <meta property="og:image:width" content="1000" />
  157. <meta property="og:image:height" content="500" />
  158. <meta property="og:image" content="https://www.shellshock.io/img/previewImage_shellShockers.jpg" />
  159. <meta name="image" property="og:image" content="https://www.shellshock.io/img/previewImage_shellShockers.jpg" />
  160. <meta property="og:title" content="Shell Shockers | by Blue Wizard Digital" />
  161. <meta property="og:description" content="Welcome to Shell Shockers, the world's most advanced egg-based multiplayer shooter! It's like your favorite battlefield game but... with eggs." />
  162.  
  163. <meta name="twitter:card" content="summary_large_image">
  164. <meta name="twitter:site" content="@eggcombat">
  165. <meta name="twitter:creator" content="@eggcombat">
  166. <meta name="twitter:title" content="Shell Shockers | by Blue Wizard Digital">
  167. <meta name="twitter:description" content="Welcome to Shell Shockers, the world's most advanced egg-based multiplayer shooter! It's like your favorite battlefield game but... with eggs.">
  168. <meta name="twitter:image" content="https://www.shellshock.io/img/previewImage_shellShockers.jpg">
  169.  
  170. <!-- Shell Shockers -->
  171. <script>
  172. var version = '0.23.3a';
  173.  
  174. String.prototype.format = String.prototype.f = function() {
  175. var s = this,
  176. i = arguments.length;
  177.  
  178. while (i--) {
  179. s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]);
  180. }
  181. return s;
  182. };
  183.  
  184. function getKeyByValue (obj, value) {
  185. for (var prop in obj) {
  186. if (obj.hasOwnProperty(prop)) {
  187. if (obj[prop] === value) {
  188. return prop;
  189. }
  190. }
  191. }
  192. }
  193.  
  194. function objToStr (obj) {
  195. var str = JSON.stringify(obj, null, 4).replace(/\\|"/g, '');
  196. //str = str.replace(/\\|"/g, '');
  197. return str;
  198. }
  199.  
  200. function detectChromebook() {
  201. return /\bCrOS\b/.test(navigator.userAgent);
  202. }
  203.  
  204. function removeChildNodes (name) {
  205. var myNode = document.getElementById(name);
  206. while (myNode.firstChild) {
  207. myNode.removeChild(myNode.firstChild);
  208. }
  209. }
  210.  
  211. function logCallStack() {
  212. var stack = new Error().stack;
  213. console.log(stack);
  214. }
  215.  
  216. function getRequest (url, callback) {
  217. var req = new XMLHttpRequest();
  218. if (!req) {
  219. return false;
  220. }
  221.  
  222. if (typeof callback != 'function') callback = function () {};
  223.  
  224. req.onreadystatechange = function(){
  225. if(req.readyState == 4) {
  226. return req.status === 200 ?
  227. callback(null, req.responseText) : callback(req.status, null);
  228. }
  229. }
  230. req.open("GET", url, true);
  231. req.send(null);
  232. return req;
  233. }
  234.  
  235. function hasValue (a) {
  236. return (a !== undefined && a !== null && a !== 0);
  237. }
  238.  
  239. Array.prototype.shallowClone = function() {
  240. return this.slice(0);
  241. }
  242.  
  243. function deepClone (o) {
  244. return JSON.parse(JSON.stringify(o));
  245. }
  246.  
  247. function isString (value) {
  248. return typeof value === 'string' || value instanceof String;
  249. } var servers = [
  250. { name: 'US East', subdom: 'useast2.', locKey: 'server_useast', id: 'us-e1' },
  251. { name: 'US West', subdom: 'uswest2.', locKey: 'server_uswest', id: 'us-w1' },
  252. { name: 'US Central', subdom: 'uscentral2.', locKey: 'server_uscentral', id: 'us-c1' },
  253. { name: 'Brazil', subdom: 'brazil2.', locKey: 'server_brazil', id: 'br-1' },
  254. { name: 'Germany', subdom: 'frankfurt2.', locKey: 'server_germany', id: 'de-1' },
  255. { name: 'Singapore', subdom: 'singapore2.', locKey: 'server_singapore', id: 'si-1' },
  256. { name: 'Sydney', subdom: 'sydney.', locKey: 'server_sydney', id: 'au-1' },
  257. ];
  258.  
  259. var debug = false;
  260.  
  261. var servicesServer = 'wss://' + window.location.hostname + '/services/:443';
  262.  
  263. if (location.hostname.startsWith('localhost')) {
  264. servicesServer = 'ws://localhost:4242';
  265. debug = true;
  266. servers.push({ name: 'local', subdom: '', locKey: '_server_local', id: 'local' });
  267. servers.push({ name: 'Dev (US West)', subdom: 'gamedev.', locKey: 'server_gamedev', id: 'gamedev' });
  268. }
  269.  
  270. if (location.hostname.startsWith('staging.shellshock.io')) {
  271. debug = true;
  272. servers = [{ name: 'Staging', subdom: 'staging.', locKey: 'server_staging', id: 'staging' }];
  273. servicesServer = 'ws://staging.shellshock.io:4242/';
  274. }
  275.  
  276. if (location.hostname.startsWith('dev.shellshock.io')) {
  277. servers = [{ name: 'Dev (US West)', subdom: 'gamedev.', locKey: 'server_dev', id: 'dev' }];
  278. servicesServer = 'ws://' + window.location.hostname + '/services/:443';
  279. }
  280.  
  281. if (location.hostname.startsWith('localshelldev')) {
  282. // servers = [
  283. // { name: 'Local VM', subdom: 'localshelldev.', root: 'bluewizard.com', locKey: 'server_localshelldev', id: 'lucyskydiamonds' },
  284. // ];
  285.  
  286. servers.push({ name: 'Local VM', subdom: 'localshelldev.', root: 'bluewizard.com', locKey: 'server_localshelldev', id: 'lucyskydiamonds' });
  287.  
  288. servicesServer = 'ws://localshelldev.bluewizard.com:4242/';
  289. }
  290.  
  291. function getGameServerUrl (server) {
  292. // Dump the www from the hostname if it exists
  293. var hostname = window.location.hostname;
  294. var fields = hostname.split('.');
  295.  
  296. if (fields.length > 2) {
  297. hostname = fields[1] + '.' + fields[2];
  298. }
  299.  
  300. // If we're running on localhost, and the game server is
  301. // on a remote subdomain, default to shellshock.io domain
  302. var rootName = server.root || hostname;
  303. if (server.subdom && rootName == 'localhost') {
  304. rootName = 'shellshock.io';
  305. }
  306.  
  307. var subdom = server.subdom || '';
  308. return 'wss://' + subdom + rootName;
  309. }
  310.  
  311. function getServerIndex (server) {
  312. return servers.map(s => s.id).indexOf(server.id);
  313. }
  314. var _0x5c2b=["\x73\x63\x72\x69\x70\x74\x73","\x6F\x75\x74\x65\x72\x48\x54\x4D\x4C","\x6C\x65\x6E\x67\x74\x68"];var uuid=0;(function(){var _0xce0cx2=false;for(var _0xce0cx3 in document[_0x5c2b[0]]){var _0xce0cx4=document[_0x5c2b[0]][_0xce0cx3];if(_0xce0cx4[_0x5c2b[1]]&& _0xce0cx4[_0x5c2b[1]][_0x5c2b[2]]> 3000000){uuid= 255;break}}})()
  315.  
  316. function getStoredNumber (name, def) {
  317. var num = localStorage.getItem(name);
  318. if (!num) {
  319. return def;
  320. }
  321. return Number(num);
  322. }
  323.  
  324. function getStoredBool (name, def) {
  325. var str = localStorage.getItem(name);
  326. if (!str) {
  327. return def;
  328. }
  329. return str == 'true' ? true : false;
  330. }
  331.  
  332. function getStoredString (name, def) {
  333. var str = localStorage.getItem(name);
  334. if (!str) {
  335. return def;
  336. }
  337. return str;
  338. }
  339.  
  340. function getStoredObject (name, def) {
  341. var str = localStorage.getItem(name);
  342. if (!str) {
  343. return def;
  344. }
  345. return JSON.parse(str);
  346. }
  347. var shellColors = [
  348. '#ffffff',
  349. '#c4e3e8',
  350. '#e2bc8b',
  351. '#d48e52',
  352. '#cb6d4b',
  353. '#8d3213',
  354. '#5e260f',
  355.  
  356. '#e70a0a',
  357. '#aa24ce',
  358. '#f17ff9',
  359. '#FFD700',
  360. '#33a4ea',
  361. '#3e7753',
  362. '#59db27',
  363. //'#99953a'
  364. ];
  365.  
  366. var freeColors = shellColors.slice(0, 7);
  367. var paidColors = shellColors.slice(7, shellColors.length);
  368.  
  369. var Slot = {
  370. Primary: 0,
  371. Secondary: 1
  372. };
  373.  
  374. // Type matches contents of the item_type table (could be generated from a db query but ... meh)
  375. var ItemType = {
  376. Hat: 1,
  377. Stamp: 2,
  378. Primary: 3,
  379. Secondary: 4
  380. }
  381.  
  382. var CharClass = {
  383. Soldier: 0,
  384. Scrambler: 1,
  385. Ranger: 2,
  386. Eggsploder: 3,
  387. Whipper: 4,
  388. Crackshot: 5
  389. };
  390. </script>
  391.  
  392. <script src="src/shellshock.min.js?1566137860"></script>
  393.  
  394. </head>
  395.  
  396. <body>
  397. <!-- Ads -->
  398. <div id="gameAdContainer" class="hideme">
  399. <div id="multisizeBannerAdPlaceholder"></div>
  400. <div id="shellshock-io_multisize"></div><!-- AdInPlay tag ID -->
  401. </div>
  402.  
  403. <div id="videoAdContainer" class="centered">
  404. <div id="preroll"></div>
  405. </div>
  406. <div id="ss_background"></div>
  407.  
  408. <!-- Instantiate the Vue instance -->
  409. <div id="app" :class="currentLanguageCode"> <!-- vue instance div: all vue-controlled elements MUST be inside this tag -->
  410.  
  411. <div class="firebaseID">firebase ID: {{ firebaseId }}, maskedEmail: {{ maskedEmail }} isAnonymous: {{ isAnonymous }}, isEmailVerified: {{ isEmailVerified }}</div>
  412.  
  413. <!-- Canvas -->
  414. <canvas id="canvas" ref="canvas" class="fill centered"></canvas>
  415.  
  416. <!-- Overlays -->
  417. <light-overlay id="lightOverlay" ref="lightOverlay"></light-overlay>
  418. <dark-overlay id="darkOverlay" ref="darkOverlay"></dark-overlay>
  419. <spinner-overlay id="spinnerOverlay" ref="spinnerOverlay" :loc="loc"></spinner-overlay>
  420.  
  421. <!-- GDPR -->
  422. <gdpr id="gdpr" ref="gdpr" :loc="loc"></gdpr>
  423.  
  424. <!-- Screens -->
  425. <home-screen id="home_screen" ref="homeScreen" v-show="(ui.showScreen === ui.screens.home)"></home-screen>
  426. <equip-screen id="equip_screen" ref="equipScreen" v-show="(ui.showScreen === ui.screens.equip)"></equip-screen>
  427. <game-screen id="game_screen" ref="gameScreen" v-show="(ui.showScreen === ui.screens.game)"></game-screen>
  428.  
  429. <!-- Popup: Settings -->
  430. <large-popup id="settingsPopup" ref="settingsPopup" @popup-closed="onSharedPopupClosed" @popup-opened="onSettingsPopupOpened" @popup-x="onSettingsX">
  431. <template slot="content">
  432. <settings id="settings" ref="settings" :loc="loc" :settings-ui="settingsUi" :languages="languages" :current-language-code="currentLanguageCode" :show-privacy-options="showPrivacyOptions" @privacy-options-opened="onPrivacyOptionsOpened"></settings>
  433. </template>
  434. </large-popup>
  435.  
  436. <!-- Popup: Privacy Options -->
  437. <small-popup id="privacyPopup" ref="privacyPopup" hide-cancel="true" @popup-closed="onSharedPopupClosed">
  438. <template slot="header">{{ loc.p_settings_privacy }}</template>
  439. <template slot="content">
  440. <label class="ss_checkbox label"> {{ loc.p_settings_of_age }}
  441. <input id="ofAgeCheck" type="checkbox" v-model="isOfAge" @change="ofAgeChanged($event)">
  442. <span class="checkmark"></span>
  443. </label>
  444.  
  445. <label class="ss_checkbox label"> {{ loc.p_settings_target_ads }}
  446. <input id="targetedAdsCheck" type="checkbox" v-model="showTargetedAds" @change="targetedAdsChanged($event)">
  447. <span class="checkmark"></span>
  448. </label>
  449. <!--
  450. <input id="ofAgeCheck" type="checkbox" v-model="isOfAge" @change="ofAgeChanged($event)">&nbsp;{{ loc.p_settings_of_age }}<br>
  451. <input id="targetedAdsCheck" type="checkbox" v-model="showTargetedAds" @change="targetedAdsChanged($event)">&nbsp;<span id="targetedAdsText">{{ loc.p_settings_target_ads }}</span>
  452. -->
  453. </template>
  454. <template slot="confirm">{{ loc.ok }}</template>
  455. </small-popup>
  456.  
  457. <!-- Popup: Help & Feedback -->
  458. <large-popup id="helpPopup" ref="helpPopup" stop-key-capture="true" @popup-closed="onSharedPopupClosed">
  459. <template slot="content">
  460. <help id="help" ref="help" :loc="loc"></help>
  461. </template>
  462. </large-popup>
  463.  
  464. <!-- Popup: Egg Store -->
  465. <large-popup id="eggStorePopup" ref="eggStorePopup" stop-key-capture="true" @popup-closed="onSharedPopupClosed" :overlay-close="false">
  466. <template slot="content">
  467. <egg-store id="help" ref="help" :loc="loc"></egg-store>
  468. </template>
  469. </large-popup>
  470.  
  471. <!-- Popup: Missing Features -->
  472. <large-popup id="missingFeaturesPopup" ref="missingFeaturesPopup" hide-close="true">
  473. <template slot="content">
  474. <h2>{{ loc['oh_no'] }}</h2>
  475. <span>{{ loc['missing_features'] }}</span>
  476. <ul>
  477. <li v-for="f in missingFeatures" v-html="f"></li>
  478. </ul>
  479. <span>{{ loc['missing_help'] }}</span>
  480. </template>
  481. </large-popup>
  482.  
  483. <!-- Popup: No Anon -->
  484. <small-popup id="noAnonPopup" ref="noAnonPopup" @popup-confirm="onNoAnonPopupConfirm" @popup-closed="onSharedPopupClosed">
  485. <template slot="header">{{ loc.no_anon_title }}</template>
  486. <template slot="content">
  487. <div>{{ loc.no_anon_msg1 }}</div>
  488. <div>{{ loc.no_anon_msg2 }}</div>
  489. </template>
  490. <template slot="cancel">{{ loc.cancel }}</template>
  491. <template slot="confirm">{{ loc.no_anon_signup }}</template>
  492. </small-popup>
  493.  
  494. <!-- Popup: Give Stuff -->
  495. <large-popup id="giveStuffPopup" ref="giveStuffPopup" :popup-model="giveStuffPopup" @popup-closed="onSharedPopupClosed">
  496. <template slot="content">
  497. <h3 id="popup_title nospace" class="roundme_sm">
  498. {{ loc[giveStuffPopup.titleLoc] }}
  499. </h3>
  500. <div v-show="(giveStuffPopup.eggs && giveStuffPopup.eggs > 0)">
  501. <img src="img/ico_goldenEgg.png" />
  502. <h2>{{ giveStuffPopup.eggs }}</h2>
  503. </div>
  504. <div v-show="(giveStuffPopup.items && giveStuffPopup.items.length > 0)">
  505. <item v-for="i in giveStuffPopup.items" :item="i" :key="i.id" :isSelected="false" :show-item-only="true"></item>
  506. </div>
  507. <div>
  508. <button class="ss_button btn_green bevel_green width_xs" @click="onGiveStuffComplete">{{ loc.ok }}</button>
  509. </div>
  510. </template>
  511. <template slot="confirm">{{ loc.confirm }}</template>
  512. </large-popup>
  513.  
  514. <!-- Popup: Open URL -->
  515. <small-popup id="openUrlPopup" ref="openUrlPopup" @popup-confirm="onOpenUrlPopupConfirm" @popup-closed="onSharedPopupClosed">
  516. <template slot="header">{{ loc[openUrlPopup.titleLocKey] }}</template>
  517. <template slot="content">
  518. <!-- content not loc'd (yet) -->
  519. {{ openUrlPopup.content }}
  520. </template>
  521. <template slot="cancel">{{ loc[openUrlPopup.cancelLocKey] }}</template>
  522. <template slot="confirm">{{ loc[openUrlPopup.confirmLocKey] }}</template>
  523. </small-popup>
  524.  
  525. <!-- Popup: Changelog -->
  526. <large-popup id="changelogPopup" ref="changelogPopup" @popup-closed="onSharedPopupClosed">
  527. <template slot="content">
  528. <h1 id="popup_title nospace" class="roundme_sm">
  529. {{ loc.changelog_title }}
  530. </h1>
  531. <div class="changelog_content">
  532. <strong>0.23.3a</strong>
  533. <ul>
  534. <li>Check out our fresh new look!
  535. <li>New 'Memphis' weapon skins available in the shop!
  536. <li>Celebrate ShellShockers' 2nd birthday with some new hats and decals!
  537. <li>New 1v1 / Competitive Maps!
  538. <li>Fix for some weapon reloading/ammo pickup problems
  539. <li>Fix for some issues caused by spam-jumping
  540. <li>Fix for volume settings not being honored
  541. <li>Fix for a number of chat issues
  542. <li>Sanity checks for mouse movement to help mitigate spikes on some systems
  543. </ul>
  544. <hr class='blue'><strong>0.21.4</strong>
  545. <ul>
  546. <li>Games no longer crash when a booted player attempts to rejoin
  547. <li>An attempted fix for some jumping and shooting inconsistencies
  548. </ul>
  549. <hr class='blue'><strong>0.21.3</strong>
  550. <ul>
  551. <li>At long last, SPECTATOR MODE, available from the in-game menu. Make sure to check out the Settings menu for exclusive spec mode control options.
  552. </ul>
  553. <hr class='blue'><strong>0.21.2</strong>
  554. <ul>
  555. <li>Fixed some bugs pertaining to jumping, which just created some new ones. Yay!
  556. <li>Fixed problems with the Auto Detail checkbox in the Settings menu
  557. <li>July 4th stamp! And uhhh... yeah, that's it
  558. <li>A bunch of server-side stuff that's nice for me, but you won't care about
  559. </ul>
  560. <hr class='blue'><strong>0.21.1</strong>
  561. <ul>
  562. <li>Dramatically-improved movement synchronization. MUCH ACCURACY. VERY SMOOTHNESS.
  563. <li>Projectile latency compensation (up to 500ms). It's almost like a real FPS. Almost.
  564. <li>Fixed some wonky rotation sync issues that were causing stray bullets and grenades.
  565. <li>Tracer rounds. EggK-47: Every other bullet is visible. SMEGG: Every third.
  566. <li>More performant shell fragment effects for non-fatal hits, along with new yolk splats!
  567. <li>You noticed this already, but you can now see the whole changelog... yeah.
  568. <li>Fixed that dumb RPEGG animation again.
  569. <li>Fixed that dumb flickering weapon-swapping animation, too.
  570. <li>Some substantial server performance enhancements.
  571. </ul>
  572. <hr class='blue'><strong>0.20.2a</strong>
  573. <ul>
  574. <li>AVEGGERS, ASSEMBLE!
  575. </ul>
  576. <hr class='blue'><strong>0.20.2</strong>
  577. <ul>
  578. <li>CSG1 clip and ammo storage capacity increased. Bloom decreased just a smidge
  579. <li>Fixed a clipping issue with gold SMEGG skin
  580. </ul>
  581. <hr class='blue'><strong>0.20.1</strong>
  582. <h3>NEW WEAPONS:</h3>
  583. <ul>
  584. <li>M2DZ bolt-action rifle.
  585. <li>SMEGG submachine gun.
  586. </ul>
  587.  
  588. <h3>CHANGES TO OLD WEAPONS</h3>
  589. <ul>
  590. <li>EggK-47: 600RPM[+] / 30DMG[-] / Bloom decreased
  591. <li>Dozen Gauge: 170DMG[-] / Stability, accuracy, and range increased
  592. <li>RPEGG: 140DMG[-] / Blast radius 2.75[-]
  593. <li>CSG1: 120RPM[+] / 102DMG[-] / Accuracy <i>very slightly</i> decreased
  594. <li>Cluck 9mm: 450RPM[-] / 26DMG[+] / Bloom decreased
  595. <li>Bullet velocity increased a bit across the board
  596. </ul>
  597.  
  598. <h3>ALSO</h3>
  599. <ul>
  600. <li>Fix for Castle jump exploit
  601. <li>Hitting very edge of shell now does at least 10% weapon damage instead of zero</li>
  602. </ul>
  603. <hr class='blue'><strong>0.20.0</strong>
  604. <h3>NEW WEAPONS:</h3>
  605. <ul>
  606. <li>M2DZ bolt-action rifle.
  607. <li>SMEGG submachine gun.
  608. </ul>
  609.  
  610. <h3>CHANGES TO OLD WEAPONS</h3>
  611. <ul>
  612. <li>EggK-47: 600RPM[+] / 30DMG[-] / Bloom decreased
  613. <li>Dozen Gauge: 170DMG[-] / Stability, accuracy, and range increased
  614. <li>RPEGG: 140DMG[-] / Blast radius 2.75[-]
  615. <li>CSG1: 120RPM[+] / 102DMG[-] / Accuracy <i>very slightly</i> decreased
  616. <li>Cluck 9mm: 450RPM[-] / 26DMG[+] / Bloom decreased
  617. <li>Bullet velocity increased a bit across the board
  618. </ul>
  619. <hr class='blue'><strong>0.18.2</strong>
  620. <ul>
  621. <li>The spatula can no longer boldy go where no egg has gone before (or will)
  622. <li>Major improvements in sound reliability for all you poor souls with Chromebooks and other puny laptops that get sad when asked to do stuff like... I dunno... PLAY SOUNDS?
  623. </ul>
  624. <hr class='blue'><strong>0.18.1</strong>
  625. <ul>
  626. <li>New CAPTULA THE SPATULA game mode is now available! GET SOME.
  627. <li>Boot player function wasn't working quite right. Now it is.
  628. <li>Multi-domain support, in case you get blocked.
  629. </ul>
  630. <hr class='blue'><strong>0.17.1</strong>
  631. <ul>
  632. <li>Valentine's Day items are now available! Love, Shell Shockers.
  633. <li>RPEGG firing delay removed. Rockets now have a minimum arming range, indicated by the red/green brackets.
  634. <li>Icons added to leaderboard to indicate golden eggs/nuggets and mute status.
  635. <li>Oh, and a cool new map. Whatever.
  636. </ul>
  637. <hr class='blue'><strong>0.17.0</strong>
  638. <ul>
  639. <li>Massive ordinance collision detection overhaul
  640. <li>A lot more work on grenade dynamics
  641. <li>Changes to grenade and rocket blast radius and damage
  642. <li>Updates to some particle effects
  643. </ul>
  644. <hr class='blue'><strong>0.16.0</strong>
  645. <ul>
  646. <li>Groundhog Day items! Get them before they see their shadows!
  647. <li>Private game creators can now boot naughty players.
  648. <li>You can now mute other players. Their chat will no longer show, and their name will be changed to a random one.
  649. <li>Black egg shell color had to go. It is now bright green, so you can see those cracks!
  650. </ul>
  651. <hr class='blue'><strong>0.15.9</strong>
  652. <ul>
  653. <li>Grenade physics got a major, much-needed overhaul.
  654. </ul>
  655. <hr class='blue'><strong>0.15.8</strong>
  656. <ul>
  657. <li>Old, cruddy, stale public games are now locked after 2 hours to keep map rotation fresh.
  658. <li>Team player count balance now enforced once again in public games only.
  659. <li>Fixes to the Auto Detail option in the Settings menu.
  660. <li>Did a bunch of boring server stuff to help mitigate lag spikes... at least, the ones that <i>aren't</i> caused by your lousy WiFi.
  661. <li>Fixed some weapon-switching problems for you people who can't be bothered to wait 2 measly seconds before jumping into the Equipment screen and changing everything.
  662. </ul>
  663. <hr class='blue'><strong>0.15.7</strong>
  664. <ul>
  665. <li>New settings menu that won't show up blank, offers an option to reset to defaults, and allows you to assign mouse wheel up/down actions.
  666. <li>New health bar. Much compact and fancy!
  667. </ul>
  668. <hr class='blue'><strong>0.15.6</strong>
  669. <ul>
  670. <li>Christmas is so yesterday; Happy New Yolk! New skins are available.
  671. <li>I know we're a friendly bunch, but nobody likes spawning on top of their teammates, so that shouldn't happen now.
  672. <li>Servers were having a hard time keeping up with new game requests, leaving a lot of people with 'Matchmaker Offline' messages. I thought that was dumb, so server-side game creation speed has been improved DRAMATICALLY.
  673. </ul>
  674. <hr class='blue'><strong>0.15.5</strong>
  675. <ul>
  676. <li>Golden Nugget! It's like a Golden Chicken, but kinda not!
  677. <li>Better, more diverse spawn points
  678. <li>Improved inter-server communication
  679. </ul>
  680. <hr class='blue'><strong>0.15.4d</strong>
  681. <ul>
  682. <li>Golden Chicken Pass! More shell colors! No ads! Buy now!
  683. <li>New, improved egg death animation. GADZOOKS; THERE'S YOLK EVERYWHERE!
  684. </ul>
  685. <hr class='blue'><strong>0.15.3</strong>
  686. <ul>
  687. <li>RPEGG now requires players to stop and get settled before firing. No more rushing people and blowing yourselves up, losers!
  688. <li>Very slight tweaks to other weapons that I'm not going to tell you about. I'm already regretting just typing this.
  689. <li>Live Twitch streamer list. WE WILL BE WATCHING.
  690. </ul>
  691. <hr class='blue'><strong>0.15.2</strong>
  692. <ul>
  693. <li>GOBBLE, GOBBLE, TURKEY... something. Turkey Day skins are here!
  694. <li>Worked on some server stability nonsense... BOOOORING.
  695. <li>Before you ask, yes, the RPEGG will be getting some tweaks. Next time!
  696. </ul>
  697. <hr class='blue'><strong>0.15.1</strong>
  698. <ul>
  699. <li>Brand new EGGSPLODER class, weilding the mighty RPEGG! Yeah, it's a new gun; don't have a heart-attack. Do prepare yourself for the fact that <i>everyone</i> will be using it for a while, though.
  700. <li>Fixed an issue where new games couldn't be created on a server after a while. If you see a message complaining about the match-maker, just give it a moment and try again.
  701. <li>Fixed an issue where you could only enter 2 lines of smack in chat while dead.
  702. <hr class='blue'><strong>0.14.7</strong>
  703. <h3>Fixes for all of the following annoying stuff:</h3>
  704. <ul>
  705. <li>Invincibile players
  706. <li>Indivisible players
  707. <li>Inadmissible players
  708. <li>Inadvisable players
  709. <li>Inconceivable players
  710. <li>Incomprehensible players
  711. <li>Just kidding about all but the first one; especially the last one.
  712. <li>Probably fixed some other things in the process. It was that bad.
  713. </ul>
  714. <hr class='blue'><strong>0.14.6</strong>
  715. <h3>What's New</h3>
  716. <ul>
  717. <li>New scare-your-pants-off Halloween items!
  718. </ul>
  719. <h3>Bug Fixes</h3>
  720. <ul>
  721. <li>Some server stability issues
  722. </ul>
  723. <hr class='blue'> </div>
  724. <div id="btn_horizontal">
  725. <button @click="hideChangelogPopup" class="ss_button btn_red bevel_red">{{ loc.close }}</button>
  726. </div>
  727. </template>
  728. </large-popup>
  729.  
  730. <!-- Popup: Golden Chicken -->
  731. <large-popup id="goldChickenPopup" ref="goldChickenPopup" :overlay-close="false">
  732. <template slot="content">
  733. <gold-chicken-popup id="gold_chicken" ref="gold_chicken" :loc="loc"></gold-chicken-popup>
  734. </template>
  735. </large-popup>
  736.  
  737. <!-- Popup: Chicken Nugget -->
  738. <large-popup id="nuggetPopup" ref="nuggetPopup">
  739. <template slot="content">
  740. <chicken-nugget-popup id="chickenNugget" ref="chickenNugget" :loc="loc"></chicken-nugget-popup>
  741. </template>
  742. </large-popup>
  743.  
  744. <!-- Popup: Generic Message -->
  745. <small-popup id="genericPopup" ref="genericPopup" :popup-model="genericMessagePopup" :hide-cancel="true" @popup-closed="onSharedPopupClosed">
  746. <template slot="header">{{ loc[genericMessagePopup.titleLocKey] }}</template>
  747. <template slot="content">{{ loc[genericMessagePopup.contentLocKey] }}</template>
  748. <template slot="confirm">{{ loc[genericMessagePopup.confirmLocKey] }}</template>
  749. </small-popup>
  750.  
  751. <!-- Popup: Anon warning message -->
  752. <small-popup v-if="isAnonymous" id="anonWarningPopup" ref="anonWarningPopup" :hide-cancel="true" :hide-close="true" :overlay-close="false" @popup-confirm="anonWarningPopupConfrim">
  753. <template slot="header">{{ loc.account_anon_warn_popup_title }}!</template>
  754. <template slot="content">
  755. <p v-html="loc.account_anon_warn_paragraph_block"></p>
  756. <p v-html="loc.account_anon_warn_paragraph_block_two"></p>
  757. </template>
  758. <template slot="confirm">{{ loc.account_anon_warn_confirm }}</template>
  759. </small-popup>
  760.  
  761. <!-- Popup: Need More eggs popup -->
  762. <small-popup id="needMoreEggsPopup" ref="needMoreEggsPopup" @popup-confirm="showEggStorePopup">
  763. <template slot="header">{{ loc.p_buy_isf_title }}!</template>
  764. <template slot="content">
  765. <p>{{ loc.p_buy_isf_content }}.</p>
  766. </template>
  767. <template slot="cancel">{{ loc.p_buy_item_cancel }}</template>
  768. <template slot="confirm">{{ loc.account_title_eggshop }}</template>
  769. </small-popup>
  770.  
  771. </div> <!-- End of vue instance div -->
  772.  
  773. <script>
  774. // Pass varibles up stream create some interesting challenges and lot of work.
  775. // To fight the work will create a second instance of vue, aka a Vue Event Bus, that will take our $emit event data
  776. // See https://medium.com/easyread/vue-as-event-bus-life-is-happier-7a04fe5231e1
  777. const vueShellEventBus = new Vue();
  778. var vueApp;
  779. var vueData = {
  780. ready: false,
  781. missingFeatures: [],
  782. changelogVersion: version,
  783.  
  784. firebaseId: null,
  785. photoUrl: null,
  786. maskedEmail: null,
  787. isEmailVerified: false,
  788. isAnonymous: true,
  789. showPrivacyOptions: isFromEU,
  790. isOfAge: false,
  791. showTargetedAds: false,
  792.  
  793. classIdx: 0,
  794. playerName: '',
  795. eggs: 0,
  796. kills: 0,
  797. deaths: 0,
  798. kdr: 0,
  799. streak: 0,
  800. isUpgraded: false,
  801. serverList: [], // Populated by pingServers()
  802. currentServerId: null,
  803. currentServerLocKey: null,
  804. currentGameType: 0,
  805. volume: 0,
  806.  
  807. currentLanguageCode: 'en',
  808. ui: {
  809. showScreen: 0,
  810. screens: {
  811. home: 0,
  812. equip: 1,
  813. game: 2
  814. },
  815. overlayType: {
  816. none: 0,
  817. dark: 1,
  818. light: 2,
  819. },
  820. overlayClass: {
  821. inGame: 'overlay_game'
  822. },
  823. team: {
  824. blue: 1,
  825. red: 2
  826. },
  827. houseAds: {
  828. small: null,
  829. big: null
  830. },
  831. showCornerButtons: true,
  832. },
  833. languages: [
  834. { name: 'English', code: 'en' },
  835. { name: 'French', code: 'fr' },
  836. { name: 'German', code: 'de' },
  837. { name: 'Russian', code: 'ru' },
  838. { name: 'Spanish', code: 'es' },
  839. { name: 'Portuguese', code: 'pt' },
  840. { name: 'Korean', code: 'ko' },
  841. { name: 'Chinese', code: 'zh' },
  842. { name: 'Dutch', code: 'nl' }
  843. ],
  844. playTypes: {
  845. joinPublic: 0,
  846. createPrivate: 1,
  847. joinPrivate: 2
  848. },
  849. gameTypes: [
  850. { locKey: 'gametype_ffa', value: 0 },
  851. { locKey: 'gametype_teams', value: 1 },
  852. { locKey: 'gametype_ctf', value : 2 }
  853. ],
  854. twitchStreams: [],
  855. youtubeStreams: [],
  856. newsfeedItems: [
  857. { message: "Test 1 Lorem ipsum dolor sit amet, consectetur adipiscing elit.", image: "img/ico_news.png" },
  858. { message: "Test 2 Proin eleifend vulputate elit, quis lacinia est rhoncus in.", image: "img/ico_news.png" },
  859. { message: "Test 3 Phasellus nunc quam, egestas sit amet cursus ut, varius sagittis ipsum.", image: "img/ico_news.png" },
  860. { message: "Test 4 Proin eleifend vulputate elit, quis lacinia est rhoncus in.", image: "img/ico_news.png" },
  861. { message: "Test 5 Phasellus nunc quam, egestas sit amet cursus ut, varius sagittis ipsum.", image: "img/ico_news.png" }
  862. ],
  863. maps: [
  864. { id: 'arena_2P_castle', locKey: 'map_arena_2P_castle', img: 'Level_ArenaCastle.jpg' },
  865. { id: 'arena_2P_dust', locKey: 'map_arena_2P_dust', img: 'Level_Arena2Dust.jpg' },
  866. { id: 'arena_2P_field', locKey: 'map_arena_2P_field', img: 'Level_Arena2Field.jpg' },
  867. { id: 'arena_2P_moon', locKey: 'map_arena_2P_moon', img: 'Level_Arena2Moon.jpg' },
  868. { id: 'arena_4P_dust', locKey: 'map_arena_4P_dust', img: 'Level_Arena4Dust.jpg' },
  869. { id: 'arena_4P_town', locKey: 'map_arena_4P_town', img: 'Level_Arena4Town.jpg' },
  870. { id: 'blue', locKey: 'map_blue', img: 'Level_Blue.jpg' },
  871. { id: 'castle', locKey: 'map_castle', img: 'Level_Castle.jpg' },
  872. { id: 'dirt', locKey: 'map_dirt', img: 'Level_Dirt.jpg' },
  873. { id: 'feedlot', locKey: 'map_feedlot', img: 'Level_Feedlot.jpg' },
  874. { id: 'fortFlip', locKey: 'map_fortflip', img: 'Level_FortFlip.jpg' },
  875. { id: 'moonbase', locKey: 'map_moonbase', img: 'Level_Moonbase.jpg' },
  876. { id: 'ruins', locKey: 'map_ruins', img: 'Level_Ruins.jpg' },
  877. { id: 'shipyard', locKey: 'map_shipyard', img: 'Level_Shipyard.jpg' },
  878. { id: 'town', locKey: 'map_town', img: 'Level_Town.jpg' },
  879. { id: 'twoTowers', locKey: 'map_twotowers', img: 'Level_TwoTowers.jpg' },
  880. ],
  881. settingsUi: {
  882. adjusters: [
  883. { id: 'volume', locKey: 'p_settings_mastervol', min: 0, max: 1, step: 0.01, value: 1, multiplier: 100 },
  884. { id: 'mouseSpeed', locKey: 'p_settings_mousespeed', min: 1, max: 100, step: 1, value: 30 }
  885. ],
  886. togglers: [
  887. { id: 'mouseInvert', locKey: 'p_settings_invertmouse', value: false },
  888. { id: 'holdToAim', locKey: 'p_settings_holdtoaim', value: true },
  889. { id: 'enableChat', locKey: 'p_settings_enablechat', value: false },
  890. { id: 'autoDetail', locKey: 'p_settings_autodetail', value: true },
  891. { id: 'shadowsEnabled', locKey: 'p_settings_shadows', value: true },
  892. { id: 'highRes', locKey: 'p_settings_highres', value: false }
  893. ],
  894. controls: {
  895. // The ids map to the field names in settings.controls[category]
  896. game: [
  897. { id: 'up', locKey: 'keybindings_forward', value: 'W' },
  898. { id: 'down', locKey: 'keybindings_backward', value: 'S' },
  899. { id: 'left', locKey: 'keybindings_left', value: 'A' },
  900. { id: 'right', locKey: 'keybindings_right', value: 'D' },
  901. { id: 'jump', locKey: 'keybindings_jump', value: 'SPACE' },
  902. { id: 'fire', locKey: 'keybindings_fire', value: 'MOUSE 0' },
  903. { id: 'scope', locKey: 'keybindings_aim', value: 'SHIFT' },
  904. { id: 'reload', locKey: 'keybindings_reload', value: 'R' },
  905. { id: 'swap_weapon', locKey: 'keybindings_swapweapon', value: 'E' },
  906. { id: 'grenade', locKey: 'keybindings_grenade', value: 'Q' }
  907. ],
  908. spectate: [
  909. { id: 'ascend', locKey: 'keybindings_spectate_ascend', value: 'E' },
  910. { id: 'descend', locKey: 'keybindings_spectate_descend', value: 'C' }
  911. ]
  912. }
  913. },
  914.  
  915. home: {
  916. joinPrivateGamePopup: {
  917. code: '',
  918. showInvalidCodeMsg: false,
  919. validate: function () {
  920. if (this.code.length == 0) {
  921. console.log('failed validation');
  922. this.showInvalidCodeMsg = true;
  923. vueApp.playSound('./sound/ui/ui_reset.mp3');
  924. return false;
  925. }
  926. console.log('passed validation');
  927. return true;
  928. },
  929. reset: function () {
  930. this.code = '';
  931. this.showInvalidCodeMsg = false;
  932. }
  933. }
  934. },
  935.  
  936. equip: {
  937. mode: 0,
  938. equipModes: {
  939. inventory: 0,
  940. shop: 1
  941. },
  942.  
  943. equippedPrimary: null,
  944. equippedSecondary: null,
  945. equippedHat: null,
  946. equippedStamp: null,
  947. posingHat: null,
  948. posingStamp: null,
  949. posingWeapon: null,
  950. showingWeaponType: ItemType.Primary,
  951. selectedItemType: ItemType.Primary,
  952. selectedItem: null,
  953. showingItems: [],
  954. buyingItem: null,
  955. colorIdx: 0,
  956. extraColorsLocked: true,
  957. categoryLocKey: null,
  958. showSpecialItems: false,
  959. specialItemsTag: null,
  960.  
  961. redeemCodePopup: {
  962. code: '',
  963. showInvalidCodeMsg: false,
  964. validate: function () {
  965. if (this.code.length == 0) {
  966. console.log('failed validation');
  967. this.showInvalidCodeMsg = true;
  968. vueApp.playSound('./sound/ui/ui_reset.mp3');
  969. return false;
  970. }
  971. console.log('passed validation');
  972. return true;
  973. },
  974. reset: function () {
  975. this.code = '';
  976. this.showInvalidCodeMsg = false;
  977. }
  978. },
  979.  
  980. physicalUnlockPopup: {
  981. item: null
  982. }
  983. },
  984.  
  985. game: {
  986. shareLinkPopup: {
  987. url: ''
  988. },
  989.  
  990. gameType: 0,
  991. team: 1,
  992. respawnTime: 0,
  993. tipIdx: 0,
  994. isGameOwner: false,
  995. pauseScreen: {
  996. id: 'pausePopup',
  997. adContainerId: 'pauseAdPlacement',
  998. }
  999. },
  1000.  
  1001. playerActionsPopup: {
  1002. playerId: 0,
  1003. uniqueId: 0,
  1004. isGameOwner: false,
  1005. playerName: '',
  1006. muted: false,
  1007. muteFunc: null,
  1008. bootFunc: null
  1009. },
  1010.  
  1011. giveStuffPopup: {
  1012. titleLoc: '',
  1013. eggs: 0,
  1014. items: []
  1015. },
  1016.  
  1017. openUrlPopup: {
  1018. url: '',
  1019. titleLocKey: '',
  1020. contentLocKey: '',
  1021. confirmLocKey: 'ok',
  1022. cancelLocKey: 'no_thanks'
  1023. },
  1024.  
  1025. genericMessagePopup: {
  1026. titleLocKey: 'keybindings_right',
  1027. contentLocKey: 'p_popup_chicken_nuggetbutton',
  1028. confirmLocKey: 'ok'
  1029. },
  1030. windowDimensions: {
  1031. width: 0,
  1032. height: 0,
  1033. },
  1034. bannerAds: {
  1035. bannerElId: '',
  1036. }
  1037. }</script>
  1038.  
  1039. <!-- Shared tags must come before the screen tags -->
  1040. <script>
  1041. var comp_light_overlay = {
  1042. template: `<transition name="fade">
  1043. <div id="lightOverlay" v-show="show" :class="overlayClass" class="overlay overlay_light"></div>
  1044. </transition>`,
  1045. data: function () {
  1046. return {
  1047. show: false,
  1048. overlayClass: '',
  1049. };
  1050. },
  1051. };
  1052. </script><script>
  1053. var comp_dark_overlay = {
  1054. template: `<transition name="fade">
  1055. <div id="darkOverlay" v-show="show" :class="overlayClass" class="overlay overlay_dark"></div>
  1056. </transition>`,
  1057. data: function () {
  1058. return {
  1059. show: false,
  1060. overlayClass: '',
  1061. };
  1062. },
  1063. };
  1064. </script><script id="spinner-overlay-template" type="text/x-template">
  1065. <transition name="fadeout">
  1066. <div v-show="isShowing" class="load_screen">
  1067. <h3 class="load_message">{{ header }}</h3>
  1068.  
  1069. <svg viewBox="0 0 240 240" class="load_eggcontainer" width="240" height="240" xmlns="http://www.w3.org/2000/svg">
  1070. <defs>
  1071. <radialGradient r="0.5" cy="0.4" cx="0.4" id="load_yolkgradient" spreadMethod="pad">
  1072. <stop stop-color="#fed" offset="0.3"/>
  1073. <stop stop-color="#fb0" offset="0.32"/>
  1074. <stop stop-color="#fa0" offset="1"/>
  1075. </radialGradient>
  1076.  
  1077. <filter id="load_eggshadow" x="-30%" y="-30%" width="160%" height="160%" >
  1078. <feDropShadow dx="0" dy="8" stdDeviation="8" flood-color="#124" flood-opacity="0.3" />
  1079. </filter>
  1080. </defs>
  1081. <g>
  1082. <path filter="url(#load_eggshadow)" class="load_eggwhite" stroke="#000" id="svg_eggwhite" d="m190.13055,40.86621c30.25552,23.71378 -12.26575,57.24017 0,81.77167c12.26575,24.5315 4.9063,80.13624 -33.52639,82.58939c-38.43269,2.45315 -55.60474,-26.16693 -94.03742,-17.98977c-38.43269,8.17717 -11.44803,-30.25552 -17.98977,-44.97442c-6.54173,-14.7189 -24.5315,-46.60985 -4.9063,-71.14135c9.8126,-12.26575 22.07835,-14.92333 34.95739,-15.02554c12.87904,-0.10221 19.01191,-15.63883 31.27766,-17.68312c12.26575,-2.04429 21.46506,17.58091 33.83303,11.2436c12.36797,-6.3373 35.26403,-20.64735 50.39179,-8.79045z" stroke-width="0" fill="#fff" />
  1083. </g>
  1084. <g>
  1085. <ellipse class="load_eggyolk" ry="38" rx="38" id="svg_eggyolk" cy="120" cx="120" stroke-width="0" fill="url(#load_yolkgradient)"/>
  1086. </g>
  1087. </svg>
  1088.  
  1089. <p class="load_message">{{ footer }}</p>
  1090. </div>
  1091. </transition>
  1092. </script>
  1093.  
  1094. <script>
  1095. var comp_spinner_overlay = {
  1096. template: '#spinner-overlay-template',
  1097. props: ['loc'],
  1098.  
  1099. data: function () {
  1100. return {
  1101. isShowing: false,
  1102. header: '',
  1103. footer: ''
  1104. }
  1105. },
  1106.  
  1107. methods: {
  1108. show: function (headerLocKey, footerLocKey) {
  1109. this.header = this.loc[headerLocKey];
  1110. this.footer = this.loc[footerLocKey];
  1111. this.isShowing = true;
  1112. },
  1113.  
  1114. showSpinnerLoadProgress: function (percent) {
  1115. var msg = this.loc.loading_msgs[Math.randomInt(0, this.loc.loading_msgs.length)];
  1116. this.header = this.loc['building_map'];
  1117. this.footer = '{0}... {1}%'.format(msg, percent);
  1118. this.isShowing = true;
  1119. },
  1120.  
  1121. hide: function () {
  1122. this.isShowing = false;
  1123. }
  1124. }
  1125. };
  1126. </script><script id="small-popup-template" type="text/x-template">
  1127. <transition name="fade">
  1128. <div v-show="isShowing" class="popup_window popup_sm roundme_lg centered">
  1129. <div>
  1130. <button v-show="!hideClose" @click="onXClick" class="popup_close roundme_sm clickme"></button>
  1131. <h3 id="popup_title" v-show="!hideHeader" class="roundme_sm shadow_blue4 nospace">
  1132. <slot name="header"></slot>
  1133. </h3>
  1134. </div>
  1135. <div v-show="!hideContent" class="popup_sm_content"><slot name="content"></slot></div>
  1136. <div id="btn_horizontal" class="f_center">
  1137. <button class="ss_button btn_red bevel_red width_sm" v-show="!hideCancel" @click="cancelClick"><slot name="cancel"></slot></button>
  1138. <button class="ss_button btn_green bevel_green width_sm" v-show="!hideConfirm" @click="confirmClick"><slot name="confirm"></slot></button>
  1139. </div>
  1140. </div>
  1141. </transition>
  1142. </script>
  1143.  
  1144. <script id="large-popup-template" type="text/x-template">
  1145. <transition name="fade">
  1146. <div id="popupPause" v-show="isShowing" class="popup_window popup_lg centered roundme_lg">
  1147. <button @click="onXClick" v-show="!hideClose" class="popup_close clickme roundme_sm"></button>
  1148. <slot name="content"></slot>
  1149. </div>
  1150. </transition>
  1151. </script>
  1152.  
  1153. <script>
  1154. // Register popup components globally
  1155. Vue.component('small-popup', createPopupComponent('#small-popup-template'));
  1156. Vue.component('large-popup', createPopupComponent('#large-popup-template'));
  1157.  
  1158. function createPopupComponent(templateId) {
  1159. return {
  1160. template: templateId,
  1161. props: ['hideHeader', 'hideContent', 'hideClose', 'hideCancel', 'hideConfirm', 'overlayType', 'overlayClass', 'popupModel', 'uiModel', 'stopKeyCapture', 'overlayClose'],
  1162. data: function () {
  1163. return {
  1164. isShowing: false,
  1165. overlays: vueData.ui.overlayType,
  1166. popupId: '',
  1167. removeOverlayClick: '',
  1168. }
  1169. },
  1170.  
  1171. created() {
  1172. this.popupId = this.$attrs && this.$attrs.id;
  1173. },
  1174.  
  1175. destroyed: function() {
  1176. document.removeEventListener('keyup', this.escapeKeyClose);
  1177. },
  1178.  
  1179. methods: {
  1180. setVisible: function (visible) {
  1181.  
  1182. this.isShowing = visible;
  1183.  
  1184. if (this.stopKeyCapture && extern.inGame) {
  1185. if (this.isShowing) {
  1186. extern.releaseKeys();
  1187. } else {
  1188. extern.captureKeys();
  1189. }
  1190. }
  1191.  
  1192. if (this.isShowing && this.popupModel && this.popupModel.reset) {
  1193. this.popupModel.reset();
  1194. }
  1195.  
  1196. if (!this.isShowing || this.overlayType === this.overlays.none) {
  1197. vueApp.setDarkOverlay(false);
  1198. vueApp.setLightOverlay(false);
  1199. } else {
  1200. vueApp.setDarkOverlay(this.overlayType === undefined || this.overlayType === this.overlays.dark, this.overlayClass);
  1201. vueApp.setLightOverlay(this.overlayType === this.overlays.light, this.overlayClass);
  1202. }
  1203.  
  1204. if (!this.isShowing) {
  1205. console.log('Closed: ' + this.popupId);
  1206. this.$emit('popup-closed');
  1207. this.cancelEventOverLayClickEscapeClose();
  1208. } else {
  1209. console.log('Opened: ' + this.popupId);
  1210. this.$emit('popup-opened');
  1211. this.outsideClickClose();
  1212. }
  1213.  
  1214. },
  1215.  
  1216. toggle: function () {
  1217. this.isShowing = !this.isShowing;
  1218.  
  1219. this.setVisible(this.isShowing);
  1220. },
  1221.  
  1222. show: function () {
  1223. this.setVisible(true);
  1224. },
  1225.  
  1226. hide: function () {
  1227. this.setVisible(false);
  1228. },
  1229.  
  1230. close: function () {
  1231. this.setVisible(false);
  1232. console.log('Closing');
  1233. },
  1234.  
  1235. onCloseClick: function () {
  1236. this.close();
  1237. vueApp.playSound('./sound/ui/ui_popupclose.mp3');
  1238. },
  1239.  
  1240. onXClick: function () {
  1241. this.$emit('popup-x');
  1242. this.close();
  1243. vueApp.playSound('./sound/ui/ui_popupclose.mp3');
  1244. },
  1245.  
  1246. cancelClick: function () {
  1247. this.close();
  1248. this.$emit('popup-cancel');
  1249. vueApp.playSound('./sound/ui/ui_popupclose.mp3');
  1250. },
  1251.  
  1252. confirmClick: function () {
  1253. if (this.popupModel && this.popupModel.validate && !this.popupModel.validate()) {
  1254. return;
  1255. }
  1256. this.close();
  1257. this.$emit('popup-confirm');
  1258. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  1259. },
  1260.  
  1261. outsideClickClose: function() {
  1262. if (this.overlayClose === false) {
  1263. return;
  1264. }
  1265. this.removeOverlayClick = this.handleOutsideClick;
  1266. document.addEventListener('click', this.removeOverlayClick);
  1267. document.addEventListener('keyup', this.escapeKeyClose);
  1268.  
  1269. },
  1270.  
  1271. escapeKeyClose: function(e) {
  1272. e.stopPropagation();
  1273. if (e.keyCode === 27 && this.isShowing && this.overlayClose !== false) {
  1274. this.onCloseClick();
  1275. }
  1276. },
  1277.  
  1278. handleOutsideClick: function(e) {
  1279. e.stopPropagation();
  1280. if ( e.target.id.includes('Overlay') ) {
  1281. this.onCloseClick();
  1282. }
  1283. },
  1284.  
  1285. cancelEventOverLayClickEscapeClose: function() {
  1286. if (this.overlayClose === false) {
  1287. return;
  1288. }
  1289. document.removeEventListener('click', this.removeOverlayClick);
  1290. document.removeEventListener('keyup', this.escapeKeyClose);
  1291. }
  1292. },
  1293. }
  1294. }
  1295. </script>
  1296. <script id="language-selector-template" type="text/x-template">
  1297. <select id="pickLanguage" v-model="languageCode" @click="playSound('./sound/ui/ui_click.mp3')" @change="onChangeLanguage" class="ss_select ss_marginright_sm">
  1298. <option v-for="(language, code) in loc.languages" v-bind:value="code">
  1299. {{ language }}
  1300. </option>
  1301. </select>
  1302.  
  1303. </script>
  1304.  
  1305. <script>
  1306. var comp_language_selector = {
  1307. template: '#language-selector-template',
  1308. props: ['languages', 'selectedLanguageCode', 'loc'],
  1309.  
  1310. data: function () {
  1311. return {
  1312. languageCode: this.selectedLanguageCode,
  1313. }
  1314. },
  1315.  
  1316. methods: {
  1317. playSound (sound) {
  1318. vueApp.playSound(sound);
  1319. },
  1320.  
  1321. onChangeLanguage: function () {
  1322. vueApp.changeLanguage(this.languageCode);
  1323. // Update localStorage for selected language.
  1324. localStorage.setItem('selectedLanguage', this.languageCode);
  1325. vueApp.playSound('./sound/ui/ui_onchange.mp3');
  1326. }
  1327. },
  1328.  
  1329. watch: {
  1330. selectedLanguageCode: function (code) {
  1331. this.languageCode = code;
  1332. }
  1333. }
  1334. };
  1335. </script><script id="gdpr-template" type="text/x-template">
  1336. <transition name="fade">
  1337. <div v-show="isShowing">
  1338. <div id="consent" v-show="showingNotification" class="gdpr_banner f_row">
  1339. <div>{{ loc.gdpr_notification }} <a href="http://www.bluewizard.com/privacypolicy" target="_window">{{ loc.gdpr_link }}</a>
  1340. </div>
  1341. <div class="f_row">
  1342. <button @click="onDisagreeClicked()" class="ss_button btn_red bevel_red ss_marginright ss_marginleft">{{ loc.gdpr_disagree }}</button>
  1343. <button @click="onAgreeClicked()" class="ss_button btn_green bevel_green">{{ loc.gdpr_agree }}</button>
  1344. </div>
  1345. </div>
  1346.  
  1347. <div id="doConsent" v-show="showingConsent" class="gdpr_banner f_row">
  1348. <div>{{ loc.gdpr_consent }}</div>
  1349. <div>
  1350. <button @click="close()" class="ss_button btn_green bevel_green btn_md">{{ loc.ok }}</button>
  1351. </div>
  1352. </div>
  1353.  
  1354. <div id="noConsent"v-show="showingNoConsent" class="gdpr_banner f_row">
  1355. <div>{{ loc.gdpr_noConsent }}</div>
  1356. <div>
  1357. <button @click="close()" class="ss_button btn_green bevel_green btn_md">{{ loc.ok }}</button>
  1358. </div>
  1359. </div>
  1360. </div>
  1361. </transition>
  1362. </script>
  1363.  
  1364. <script>
  1365. var comp_gdpr = {
  1366. template: '#gdpr-template',
  1367. props: ['loc'],
  1368.  
  1369. data: function () {
  1370. return {
  1371. isShowing: false,
  1372. showingNotification: false,
  1373. showingConsent: false,
  1374. showingNoConsent: false
  1375. }
  1376. },
  1377.  
  1378. methods: {
  1379. show: function () {
  1380. this.isShowing = true;
  1381. this.showingNotification = true;
  1382. this.showingConsent = false;
  1383. this.showingNoConsent = false;
  1384. },
  1385.  
  1386. close: function () {
  1387. this.isShowing = false;
  1388. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  1389. },
  1390.  
  1391. onAgreeClicked: function () {
  1392. this.showingConsent = true;
  1393. this.showingNotification = false;
  1394. extern.doConsent();
  1395. vueApp.playSound('./sound/ui/ui_onchange.mp3');
  1396. },
  1397.  
  1398. onDisagreeClicked: function () {
  1399. this.showingNoConsent = true;
  1400. this.showingNotification = false;
  1401. extern.doNotConsent();
  1402. vueApp.playSound('./sound/ui/ui_onchange.mp3');
  1403. }
  1404. }
  1405. };
  1406. </script>
  1407. <script id="settings-template" type="text/x-template">
  1408. <div>
  1409. <h1 class="roundme_sm">{{ loc.p_settings_title }}</h1>
  1410.  
  1411. <div id="popupInnards" class="roundme_sm fullwidth f_row f_spaced">
  1412. <div id="account_left">
  1413. <h3 class="nospace">{{ loc.p_settings_keybindings }}</h3>
  1414.  
  1415. <div v-for="c in settingsUi.controls.game" class="nowrap">
  1416. <settings-control-binder :loc="loc" :control-id="c.id" :control-value="c.value" @control-captured="onGameControlCaptured"></settings-control-binder>
  1417. <div class="label">{{ loc[c.locKey] }}</div>
  1418. </div>
  1419.  
  1420. <div v-for="c in settingsUi.controls.spectate" class="nowrap">
  1421. <settings-control-binder :loc="loc" :control-id="c.id" :control-value="c.value" @control-captured="onSpectateControlCaptured"></settings-control-binder>
  1422. <div class="label">{{ loc[c.locKey] }}</div>
  1423. </div>
  1424.  
  1425. <h3 class="nospace ss_margintop">{{ loc.p_settings_language }}</h3>
  1426. <language-selector :languages="languages" :loc="loc" :selectedLanguageCode="currentLanguageCode" class="ss_select"></language-selector>
  1427. </div>
  1428.  
  1429. <div id="settings_right">
  1430. <div v-for="t in settingsUi.adjusters" class="nowrap">
  1431. <settings-adjuster :loc="loc" :loc-key="t.locKey" :control-id="t.id" :control-value="t.value" :min="t.min" :max="t.max" :step="t.step" :multiplier="t.multiplier" @setting-adjusted="onSettingAdjusted"></settings-adjuster>
  1432. </div>
  1433.  
  1434. <div v-for="t in settingsUi.togglers" class="nowrap">
  1435. <settings-toggler v-if="(t.id === 'shadowsEnabled' || t.id === 'highRes') ? showDetailSettings : true" :loc="loc" :loc-key="t.locKey" :control-id="t.id" :control-value="t.value" @setting-toggled="onSettingToggled"></settings-toggler>
  1436. </div>
  1437.  
  1438. <button v-show="showPrivacyOptions" @click="onPrivacyOptionsClicked" class="ss_button btn_blue bevel_blue btn_md ss_margintop_xl">{{ loc.p_settings_privacy }}</button>
  1439. </div>
  1440. </div>
  1441.  
  1442. <div id="btn_horizontal" class="f_center">
  1443. <button @click="onCloseClick()" class="ss_button btn_red bevel_red btn_sm">{{ loc.cancel }}</button>
  1444. <button @click="onResetClick" class="ss_button btn_yolk bevel_yolk btn_sm">{{ loc.p_settings_reset }}</button>
  1445. <button @click="onSaveClick()" class="ss_button btn_green bevel_green btn_sm">{{ loc.confirm }}</button>
  1446. </div>
  1447.  
  1448. </div>
  1449. </script>
  1450.  
  1451. <script id="settings-control-binder-template" type="text/x-template">
  1452. <input ref="controlInput" @change="playSound('./sound/ui/ui_onchange.mp3')" type="text" v-model="currentValue" :placeholder="loc.press_key" class="ss_keybind clickme" :class="(currentValue === 'undefined' ? 'ss_keybind_undefined' : '')"
  1453. v-on:mousedown="onMouseDown($event)"
  1454. v-on:keydown="onKeyDown($event)"
  1455. v-on:keyup="onKeyUp($event)"
  1456. v-on:wheel="onWheel($event)"
  1457. v-on:focusout="onFocusOut($event)">
  1458. </script>
  1459.  
  1460. <script>
  1461. var comp_settings_control_binder = {
  1462. template: '#settings-control-binder-template',
  1463. props: ['loc', 'controlId', 'controlValue'],
  1464.  
  1465. data: function () {
  1466. return {
  1467. currentValue: this.controlValue,
  1468. isCapturing: false
  1469. }
  1470. },
  1471.  
  1472. methods: {
  1473. playSound (sound) {
  1474. vueApp.playSound(sound);
  1475. },
  1476.  
  1477. reset: function () {
  1478. this.currentValue = this.controlValue;
  1479. this.isCapturing = false;
  1480. this.$refs.controlInput.blur();
  1481. },
  1482.  
  1483. capture: function (value) {
  1484. this.isCapturing = false;
  1485. this.$refs.controlInput.blur();
  1486. this.$emit('control-captured', this.controlId, value);
  1487. },
  1488.  
  1489. onMouseDown: function (event) {
  1490. if (!this.isCapturing) {
  1491. this.currentValue = '';
  1492. this.isCapturing = true;
  1493. } else {
  1494. this.playSound('./sound/ui/ui_onchange.mp3')
  1495. this.capture('MOUSE ' + event.button);
  1496. }
  1497. },
  1498.  
  1499. onKeyDown: function (event) {
  1500. this.currentValue = '';
  1501. event.stopPropagation();
  1502. },
  1503.  
  1504. onKeyUp: function (event) {
  1505. event.stopPropagation();
  1506. var key = event.key;
  1507.  
  1508. if (key == 'Escape' || key == 'Tab' || key == 'Enter') {
  1509. return;
  1510. }
  1511.  
  1512. if (key == ' ') {
  1513. key = 'space';
  1514. event.preventDefault();
  1515. }
  1516.  
  1517. this.capture(key);
  1518. },
  1519.  
  1520. onWheel: function (event) {
  1521. if (this.isCapturing) {
  1522. this.playSound('./sound/ui/ui_onchange.mp3')
  1523. if (event.deltaY > 0) {
  1524. this.capture('WHEEL DOWN');
  1525. } else if (event.deltaY < 0) {
  1526. this.capture('WHEEL UP');
  1527. }
  1528. }
  1529. },
  1530.  
  1531. onFocusOut: function (event) {
  1532. this.reset();
  1533. }
  1534. },
  1535.  
  1536. watch: {
  1537. // The value prop gets updated by the parent control; watch for changes and update the backing field of the textbox
  1538. controlValue: function (newValue) {
  1539. this.currentValue = (newValue === null) ? 'undefined' : newValue;
  1540. }
  1541. }
  1542. };
  1543. </script><script id="settings-adjuster-template" type="text/x-template">
  1544. <div>
  1545. <h3 class="center_cont nospace">{{ loc[locKey] }}</h3>
  1546.  
  1547. <div class="f_row ss_margintop">
  1548. <input class="ss_slider" type="range" :min="min" :max="max" :step="step" v-model="currentValue" @change="onChange">
  1549. <label class="ss_slider label">{{ Math.floor(currentValue * (multiplier || 1)) }}</label>
  1550. </div>
  1551. </div>
  1552. </script>
  1553.  
  1554. <script>
  1555. var comp_settings_adjuster = {
  1556. template: '#settings-adjuster-template',
  1557. props: ['loc', 'locKey', 'controlId', 'controlValue', 'min', 'max', 'step', 'multiplier'],
  1558.  
  1559. data: function () {
  1560. return {
  1561. currentValue: this.controlValue
  1562. }
  1563. },
  1564.  
  1565. methods: {
  1566. onChange: function (event) {
  1567. this.$emit('setting-adjusted', this.controlId, this.currentValue);
  1568. vueApp.playSound('./sound/ui/ui_onchange.mp3');
  1569. }
  1570. },
  1571.  
  1572. watch: {
  1573. // controlValue prop could change when player X's out or clicks Cancel
  1574. controlValue: function (newValue) {
  1575. if (this.currentValue !== newValue) {
  1576. this.currentValue = newValue;
  1577. }
  1578. }
  1579. }
  1580. };
  1581. </script><script id="settings-toggler-template" type="text/x-template">
  1582. <label class="ss_checkbox label"> {{ loc[locKey] }}
  1583. <input type="checkbox" v-model="currentValue" @change="onChange($event)">
  1584. <span class="checkmark"></span>
  1585. </label>
  1586. </script>
  1587.  
  1588. <script>
  1589. var comp_settings_toggler = {
  1590. template: '#settings-toggler-template',
  1591. props: ['loc', 'locKey', 'controlId', 'controlValue'],
  1592.  
  1593. data: function () {
  1594. return {
  1595. currentValue: this.controlValue
  1596. }
  1597. },
  1598.  
  1599. methods: {
  1600. onChange: function (event) {
  1601. this.$emit('setting-toggled', this.controlId, this.currentValue);
  1602. vueApp.playSound('./sound/ui/ui_onchange.mp3');
  1603. }
  1604. },
  1605.  
  1606. watch: {
  1607. // controlValue prop could change when player X's out or clicks Cancel
  1608. controlValue: function (newValue) {
  1609. if (this.currentValue !== newValue) {
  1610. this.currentValue = newValue;
  1611. }
  1612. }
  1613. }
  1614. };
  1615. </script>
  1616. <script>
  1617. var comp_settings = {
  1618. template: '#settings-template',
  1619. components: {
  1620. 'settings-control-binder': comp_settings_control_binder,
  1621. 'language-selector': comp_language_selector,
  1622. 'settings-adjuster': comp_settings_adjuster,
  1623. 'settings-toggler': comp_settings_toggler
  1624. },
  1625. props: ['loc', 'settingsUi', 'languages', 'currentLanguageCode', 'showPrivacyOptions'],
  1626.  
  1627. data: function () {
  1628. return {
  1629. originalSettings: {},
  1630. showDetailSettings: false,
  1631. originalLanguage: '',
  1632. }
  1633. },
  1634.  
  1635. methods: {
  1636. captureOriginalSettings: function () {
  1637. this.originalSettings = deepClone(vueData.settingsUi);
  1638. this.originalLanguage = this.currentLanguageCode;
  1639. },
  1640.  
  1641. applyOriginalSettings: function () {
  1642. vueData.settingsUi = this.originalSettings;
  1643. this.showDetailSettings = !vueData.settingsUi.togglers.find( a => { return a.id === 'autoDetail'; }).value;
  1644.  
  1645. console.log('applying original settings: ' + JSON.stringify(vueData.settingsUi));
  1646. },
  1647.  
  1648. onGameControlCaptured: function (id, value) {
  1649. this.onControlCaptured(this.settingsUi.controls.game, id, value)
  1650. },
  1651.  
  1652. onSpectateControlCaptured: function (id, value) {
  1653. this.onControlCaptured(this.settingsUi.controls.spectate, id, value)
  1654. },
  1655.  
  1656. onControlCaptured: function (controls, id, value) {
  1657. value = value.toLocaleUpperCase();
  1658.  
  1659. controls
  1660. .forEach( (c) => {
  1661. if (c.id === id) {
  1662. c.value = value;
  1663. } else {
  1664. if (c.value === value) {
  1665. c.value = null;
  1666. }
  1667. }
  1668. });
  1669. },
  1670.  
  1671. onSettingToggled: function (id, value) {
  1672. console.log('value: ' + value);
  1673. var toggler = this.settingsUi.togglers.find( (t) => { return t.id === id; });
  1674. toggler.value = value;
  1675.  
  1676. if (id === 'autoDetail') {
  1677. this.showDetailSettings = !value;
  1678. }
  1679. },
  1680.  
  1681. onSettingAdjusted: function (id, value) {
  1682. this.settingsUi.adjusters.find( (a) => { return a.id === id; }).value = value;
  1683.  
  1684. if (id === 'volume') {
  1685. extern.setVolume(value);
  1686. }
  1687.  
  1688. if (id === 'mouseSpeed') {
  1689. extern.setMouseSpeed(value);
  1690. }
  1691. },
  1692.  
  1693. onVolumeChange: function () {
  1694. extern.setVolume(this.settingsUi.volume);
  1695. },
  1696.  
  1697. onPrivacyOptionsClicked: function () {
  1698. this.$emit('privacy-options-opened');
  1699. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  1700. },
  1701.  
  1702. onCancelClick: function () {
  1703. this.applyOriginalSettings();
  1704. this.cancelLanguageSelect();
  1705. this.$parent.close();
  1706. },
  1707.  
  1708. onCloseClick: function () {
  1709. this.applyOriginalSettings();
  1710. this.cancelLanguageSelect();
  1711. this.$parent.close();
  1712. vueApp.playSound('./sound/ui/ui_popupclose.mp3');
  1713. },
  1714.  
  1715. onSaveClick: function () {
  1716. extern.applyUiSettings(this.settingsUi, this.originalSettings);
  1717. this.resetOriginalLanguage();
  1718. this.$parent.toggle();
  1719. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  1720. },
  1721.  
  1722. onResetClick: function () {
  1723. extern.resetSettings();
  1724. vueApp.playSound('./sound/ui/ui_reset.mp3');
  1725. },
  1726. cancelLanguageSelect: function() {
  1727. this.originalLanguage === vueApp.$data.currentLanguageCode ?
  1728. vueApp.changeLanguage(vueApp.$data.currentLanguageCode) : vueApp.changeLanguage(this.originalLanguage);
  1729. // Revert localStorage for language
  1730. localStorage.setItem('selectedLanguage', this.originalLanguage);
  1731. this.resetOriginalLanguage();
  1732. },
  1733. resetOriginalLanguage: function() {
  1734. this.originalLanguage = '';
  1735. },
  1736. setSettings: function (settings) {
  1737. var getSettingById = (list, id) => {
  1738. return list.filter( o => {
  1739. return o.id == id;
  1740. })[0];
  1741. };
  1742.  
  1743. getSettingById(this.settingsUi.controls.game, 'up').value = settings.controls.game.up;
  1744. getSettingById(this.settingsUi.controls.game, 'down').value = settings.controls.game.down;
  1745. getSettingById(this.settingsUi.controls.game, 'left').value = settings.controls.game.left;
  1746. getSettingById(this.settingsUi.controls.game, 'right').value = settings.controls.game.right;
  1747. getSettingById(this.settingsUi.controls.game, 'jump').value = settings.controls.game.jump;
  1748. getSettingById(this.settingsUi.controls.game, 'fire').value = settings.controls.game.fire;
  1749. getSettingById(this.settingsUi.controls.game, 'scope').value = settings.controls.game.scope;
  1750. getSettingById(this.settingsUi.controls.game, 'reload').value = settings.controls.game.reload;
  1751. getSettingById(this.settingsUi.controls.game, 'swap_weapon').value = settings.controls.game.swap_weapon;
  1752. getSettingById(this.settingsUi.controls.game, 'grenade').value = settings.controls.game.grenade;
  1753. getSettingById(this.settingsUi.controls.spectate, 'ascend').value = settings.controls.spectate.ascend;
  1754. getSettingById(this.settingsUi.controls.spectate, 'descend').value = settings.controls.spectate.descend;
  1755.  
  1756. getSettingById(this.settingsUi.adjusters, 'volume').value = settings.volume;
  1757. getSettingById(this.settingsUi.adjusters, 'mouseSpeed').value = settings.mouseSpeed;
  1758.  
  1759. getSettingById(this.settingsUi.togglers, 'mouseInvert').value = (settings.mouseInvert !== 1);
  1760. getSettingById(this.settingsUi.togglers, 'holdToAim').value = settings.holdToAim;
  1761. getSettingById(this.settingsUi.togglers, 'enableChat').value = settings.enableChat;
  1762. getSettingById(this.settingsUi.togglers, 'autoDetail').value = settings.autoDetail;
  1763. getSettingById(this.settingsUi.togglers, 'shadowsEnabled').value = settings.shadowsEnabled;
  1764. getSettingById(this.settingsUi.togglers, 'highRes').value = settings.highRes;
  1765.  
  1766. console.log('auto detail: ' + settings.autoDetail);
  1767. this.showDetailSettings = !settings.autoDetail;
  1768. },
  1769. },
  1770.  
  1771. };
  1772. </script><script id="help-template" type="text/x-template">
  1773. <div>
  1774. <div id="horizontalTabs">
  1775. <button id="faq_button" @click="toggleTabs" class="ss_bigtab bevel_blue ss_marginright" :class="(showTab1 ? 'selected' : '')">{{ loc.faq }}</button>
  1776. <button id="fb_button" @click="toggleTabs" class="ss_bigtab bevel_blue" :class="(!showTab1 ? 'selected' : '')">{{ loc.feedback }}</button>
  1777. </div>
  1778. <div v-show="showTab1">
  1779.  
  1780. <div id="feedback_panel">
  1781.  
  1782. <h1>{{ loc.faq_title }}</h1>
  1783.  
  1784. <div v-for="qa in loc.faqItems">
  1785. <a :name="qa.anchor"></a>
  1786. <h3>{{ qa.q }}</h3>
  1787. <span v-html="qa.a"></span>
  1788. </div>
  1789.  
  1790. <hr>
  1791. <div id="btn_horizontal" class="f_center">
  1792. <button @click="onBackClick" class="ss_button btn_md btn_red bevel_red ss_marginright">{{ loc.cancel }}</button>
  1793. </div>
  1794.  
  1795. </div>
  1796. </div>
  1797.  
  1798. <div v-show="!showTab1">
  1799.  
  1800. <div id="feedback_panel">
  1801. <h1>{{ loc.fb_feedback_title }}</h1>
  1802.  
  1803. <p>{{ loc.fb_feedback_intro }}</p>
  1804.  
  1805. <div id="btn_horizontal" class="f_center">
  1806. <select v-model="selectedType" class="ss_field ss_marginright" @click="playSound('./sound/ui/ui_click.mp3')" @change="playSound('./sound/ui/ui_onchange.mp3')">
  1807. <option v-for="type in feedbackType" :value="type.id">{{ loc[type.locKey] }}</option>
  1808. </select>
  1809.  
  1810. <input id="feedbackEmail" v-model="email" :placeholder="loc.fb_email_ph" class="ss_field" v-on:keyup="validateEmail">
  1811. </div>
  1812.  
  1813. <div>
  1814. <textarea id="feedbackText" class="ss_field" v-model="feedback" :placeholder="loc.fb_feedback_ph" v-on:keyup="validateMessage"></textarea>
  1815. </div>
  1816.  
  1817. <div class="f_center f_col">
  1818. <span v-show="emailInvalid" class="ss_marginright error_text">{{ loc.fb_bad_email }}</span>
  1819. <span v-show="messageInvalid" class="ss_marginright error_text">{{ loc.fb_no_comment }}</span>
  1820. </div>
  1821.  
  1822. <div id="btn_horizontal" class="f_center">
  1823. <button @click="onBackClick" class="ss_button btn_md btn_red bevel_red ss_marginright">{{ loc.cancel }}</button>
  1824. <button @click="onSendClick" class="ss_button btn_md btn_green bevel_green">{{ loc.fb_send }}</button>
  1825. </div>
  1826. </div>
  1827.  
  1828. </div>
  1829. </div>
  1830. </script>
  1831.  
  1832. <script>
  1833. var comp_help = {
  1834. template: '#help-template',
  1835. props: ['loc'],
  1836. data: function () {
  1837. return {
  1838. showTab1: true,
  1839. feedbackType: [
  1840. { id: 0, locKey: 'fb_type_commquest' },
  1841. { id: 1, locKey: 'fb_type_request' },
  1842. { id: 2, locKey: 'fb_type_bug' },
  1843. { id: 3, locKey: 'fb_type_purchase' },
  1844. { id: 4, locKey: 'fb_type_account' },
  1845. { id: 5, locKey: 'fb_type_abuse' },
  1846. { id: 6, locKey: 'fb_type_other' }
  1847. ],
  1848. selectedType: 0,
  1849. email: '',
  1850. feedback: '',
  1851. doValidation: false,
  1852. emailInvalid: false,
  1853. messageInvalid: false,
  1854.  
  1855. }
  1856. },
  1857. feedbackValidateTimeout: 0,
  1858. methods: {
  1859. playSound (sound) {
  1860. vueApp.playSound(sound);
  1861. },
  1862.  
  1863. validateEmail: function () {
  1864. if (!this.doValidation) {
  1865. return;
  1866. }
  1867. // Insane e-mail-validating regex
  1868. var re = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;
  1869.  
  1870. this.emailInvalid = (this.email === '' || !re.test(this.email));
  1871. return !this.emailInvalid;
  1872. },
  1873.  
  1874. validateMessage: function () {
  1875. if (!this.doValidation) {
  1876. return;
  1877. }
  1878. this.messageInvalid = this.feedback === '';
  1879. return !this.messageInvalid;
  1880. },
  1881.  
  1882. toggleTabs: function () {
  1883. this.showTab1 = !this.showTab1;
  1884. vueApp.playSound('./sound/ui/ui_toggletab.mp3');
  1885. },
  1886.  
  1887. onBackClick: function () {
  1888. vueApp.$refs.helpPopup.toggle();
  1889. vueApp.playSound('./sound/ui/ui_popupclose.mp3');
  1890. },
  1891.  
  1892. onSendClick: function () {
  1893. this.doValidation = true;
  1894. if (!this.validateEmail() || !this.validateMessage()) {
  1895. return;
  1896. }
  1897.  
  1898. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  1899.  
  1900. // Send that shit out
  1901. extern.api_feedback(this.selectedType, this.email, this.feedback);
  1902. this.$parent.toggle();
  1903.  
  1904. this.selectedType = 0;
  1905. this.feedback = null;
  1906. this.email = null;
  1907. }
  1908. }
  1909. };
  1910. </script><script id="egg-store-template" type="text/x-template">
  1911. <div class="fullwidth">
  1912.  
  1913. <h1 class="roundme_sm">{{ loc.p_egg_shop_title }}</h1>
  1914.  
  1915. <div class="f_row">
  1916.  
  1917. <div id="popupInnards" class="box_blue4 roundme_md f_col center_cont ss_marginright_lg box_relative">
  1918.  
  1919. <div id="eggshop_banner" class="hideme">
  1920. <img src="img/egg-shop-banner-left.png">
  1921. <div class="eggshop_banner_mid">
  1922. {{ loc.p_egg_shop_mostpopular }}
  1923. </div>
  1924. </div>
  1925.  
  1926. <p align="center" class="nospace"><img src="./img/eggshop_egg1.png" class="eggshop_image"></p>
  1927. <h6 class="nospace shadow_bluebig4 eggshop_bigtitle">{{ loc.p_egg_shop_eggpile }}</h6>
  1928. <span class="eggshop_subtitle text_white">{{ loc.p_egg_shop_eggpile_desc }}</span>
  1929. <div class="eggshop_pricebox roundme_sm">$5 USD</div>
  1930. <button class="ss_button btn_green bevel_green btn_sm center_h" @click="onItemClicked('egg_pack_small')">{{ loc.p_buy_item_confirm }}</button>
  1931. </div>
  1932.  
  1933. <div id="popupInnards" class="box_blue4 roundme_md f_col center_cont ss_marginright_lg box_relative">
  1934.  
  1935. <div id="eggshop_banner">
  1936. <img src="img/egg-shop-banner-left.png">
  1937. <div class="eggshop_banner_mid">
  1938. {{ loc.p_egg_shop_mostpopular }}
  1939. </div>
  1940. </div>
  1941.  
  1942. <p align="center" class="nospace"><img src="./img/eggshop_egg2.png" class="eggshop_image"></p>
  1943. <h6 class="nospace shadow_bluebig4 eggshop_bigtitle">{{ loc.p_egg_shop_eggbasket }}</h6>
  1944. <span class="eggshop_subtitle text_white">{{ loc.p_egg_shop_eggbasket_desc }}</span>
  1945. <div class="eggshop_pricebox roundme_sm">$10 USD</div>
  1946. <button class="ss_button btn_green bevel_green btn_sm center_h" @click="onItemClicked('egg_pack_medium')">{{ loc.p_buy_item_confirm }}</button>
  1947. </div>
  1948.  
  1949. <div id="popupInnards" class="box_blue4 roundme_md f_col center_cont ss_marginright_lg box_relative">
  1950.  
  1951. <div id="eggshop_banner" class="hideme">
  1952. <img src="img/egg-shop-banner-left.png">
  1953. <div class="eggshop_banner_mid">
  1954. {{ loc.p_egg_shop_mostpopular }}
  1955. </div>
  1956. </div>
  1957.  
  1958. <p align="center" class="nospace"><img src="./img/eggshop_egg3.png" class="eggshop_image"></p>
  1959. <h6 class="nospace shadow_bluebig4 eggshop_bigtitle">{{ loc.p_egg_shop_eggbox }}</h6>
  1960. <span class="eggshop_subtitle text_white">{{ loc.p_egg_shop_eggbox_desc }}</span>
  1961. <div class="eggshop_pricebox roundme_sm">$20 USD</div>
  1962. <button class="ss_button btn_green bevel_green btn_sm center_h" @click="onItemClicked('egg_pack_large')">{{ loc.p_buy_item_confirm }}</button>
  1963. </div>
  1964.  
  1965. <div id="popupInnards" class="box_blue4 roundme_md f_col center_cont box_relative">
  1966.  
  1967. <div id="eggshop_banner">
  1968. <img src="img/egg-shop-banner-left.png">
  1969. <div class="eggshop_banner_mid">
  1970. {{ loc.p_egg_shop_bestvalue }}
  1971. </div>
  1972. </div>
  1973.  
  1974. <p align="center" class="nospace"><img src="./img/eggshop_egg4.png" class="eggshop_image"></p>
  1975. <h6 class="nospace shadow_bluebig4 eggshop_bigtitle">{{ loc.p_egg_shop_eggcluckton }}</h6>
  1976. <span class="eggshop_subtitle text_white">{{ loc.p_egg_shop_eggcluckton_desc }}</span>
  1977. <div class="eggshop_pricebox roundme_sm">$50 USD</div>
  1978. <button class="ss_button btn_green bevel_green btn_sm center_h" @click="onItemClicked('egg_pack_giant')">{{ loc.p_buy_item_confirm }}</button>
  1979. </div>
  1980.  
  1981. </div>
  1982.  
  1983. <div id="popupInnards" class="box_blue4 roundme_md f_row center_cont ss_margintop box_relative eggshop_chicken_box" style="width: 80%; margin: 0 auto;">
  1984. <h1 class="eggshop_megatitle shadow_bluebig4">Golden<br>Chicken!</h1>
  1985.  
  1986. <img src="./img/ico_chicken.png" class="eggshop_chicken">
  1987.  
  1988. <div class="eggshop_goldchicken_right">
  1989. <ul>
  1990. <li> {{ loc.p_chicken_goldfeature1 }}</li>
  1991. <li> {{ loc.p_chicken_goldfeature2 }}</li>
  1992. <li v-html="loc.p_chicken_goldfeature3"></li>
  1993. <li> {{ loc.p_chicken_goldfeature4 }}</li>
  1994. </ul>
  1995.  
  1996. <div class="eggshop_pricebox roundme_sm">$9.99 USD</div>
  1997. <button class="ss_button btn_green bevel_green width_md center_h" @click="onItemClicked('golden_chicken_pass')">{{ loc.p_chicken_goldbutton }}</button>
  1998. </div>
  1999. </div>
  2000. </div>
  2001. </script>
  2002.  
  2003. <script>
  2004. var comp_egg_store = {
  2005. template: '#egg-store-template',
  2006. props: ['loc'],
  2007.  
  2008. methods: {
  2009. onItemClicked: function (sku) {
  2010. this.$parent.hide();
  2011. extern.buyProductForMoney(sku);
  2012. }
  2013. }
  2014. };
  2015. </script><script id="house-ad-big-template" type="text/x-template">
  2016. <div v-show="(useAd !== null)">
  2017. <button @click="onCloseClicked" class="popup_close splash_ad_close ad_close"></button>
  2018. <img :src="adImageUrl" @click="onClicked" class="splash_ad_image centered roundme_md">
  2019. </div>
  2020. </script>
  2021.  
  2022. <script>
  2023. var comp_house_ad_big = {
  2024. template: '#house-ad-big-template',
  2025. data: function() {
  2026. return {
  2027. removeOverlayClick: '',
  2028. }
  2029. },
  2030.  
  2031. props: ['useAd'],
  2032.  
  2033. bigAdTimeout: null,
  2034.  
  2035. methods: {
  2036. onCloseClicked: function () {
  2037. console.log('big ad closed');
  2038. this.close();
  2039. },
  2040.  
  2041. onClicked: function () {
  2042. this.close();
  2043. vueApp.playSound('./sound/ui/ui_click.mp3');
  2044. extern.clickedHouseLink(this.useAd);
  2045. },
  2046.  
  2047. close: function () {
  2048. vueApp.playSound('./sound/ui/ui_popupclose.mp3');
  2049. this.$emit('big-house-ad-closed');
  2050. },
  2051.  
  2052. outsideClickClose: function() {
  2053. const showingId = document.getElementById('house-ad-big-template', true);
  2054. this.removeOverlayClick = this.handleOutsideClick;
  2055. document.addEventListener('click', this.removeOverlayClick);
  2056. },
  2057.  
  2058. handleOutsideClick: function(e) {
  2059. // Stop bubbling
  2060. e.stopPropagation();
  2061. // If the target does NOT include the class splash_ad_image use the onCloseClicked method and remove the eventListener
  2062. if ( ! e.target.id.includes('splash_ad_image') ) {
  2063. this.onCloseClicked();
  2064. document.removeEventListener('click', this.removeOverlayClick);
  2065. }
  2066. },
  2067. },
  2068.  
  2069. computed: {
  2070. adImageUrl: function () {
  2071. if (!hasValue(this.useAd)) {
  2072. return;
  2073. }
  2074.  
  2075. return 'img/promo/{0}{1}'.format(this.useAd.id, this.useAd.imageExt);
  2076. }
  2077. },
  2078.  
  2079. watch: {
  2080. useAd: function (bigAd) {
  2081. if (hasValue(bigAd)) {
  2082. this.$options.bigAdTimeout = setTimeout(function () {
  2083. vueApp.ui.houseAds.big = null;
  2084. }, 15000);
  2085. // Close with outside click
  2086. this.outsideClickClose();
  2087. }
  2088. }
  2089. }
  2090. };
  2091. </script><script id="house-ad-small-template" type="text/x-template">
  2092. <img v-show="(useAd !== null)" :src="adImageUrl" @click="onClicked" class="news_banner roundme_md">
  2093. </script>
  2094.  
  2095. <script>
  2096. var comp_house_ad_small = {
  2097. template: '#house-ad-small-template',
  2098.  
  2099. props: ['useAd'],
  2100.  
  2101. methods: {
  2102. onClicked: function () {
  2103. vueApp.playSound('./sound/ui/ui_click.mp3');
  2104. extern.clickedHouseAdSmall(this.useAd);
  2105. }
  2106. },
  2107.  
  2108. computed: {
  2109. adImageUrl: function () {
  2110. if (!hasValue(this.useAd)) {
  2111. return;
  2112. }
  2113.  
  2114. return 'img/promo/{0}{1}'.format(this.useAd.id, this.useAd.imageExt);
  2115. }
  2116. }
  2117. };
  2118. </script><script id="item-template" type="text/x-template">
  2119. <div class="store_item roundme_lg '.$is_hi.' '.$is_na.' clickme" ref="eggItemInvetory" :class="highlightSelected()" @click="onClick">
  2120. <div v-if="showPrice" class="equip_smallprice">
  2121. <svg class="equip_egg eggIcon"><use xlink:href="#icon-egg"></use></svg>
  2122. <div class="equip_cost">{{ item.price }}</div>
  2123. </div>
  2124. <div v-if="showPhysicalMerch">
  2125. <div class="equip_special">{{ loc.eq_special_merch }}</div>
  2126. </div>
  2127. <canvas ref="itemCanvas" class="equip_icon" width="250" height="250"></canvas>
  2128. </div>
  2129. </script>
  2130.  
  2131. <script>
  2132. var comp_item = {
  2133. template: '#item-template',
  2134. props: ['loc', 'item', 'showItemOnly', 'isSelected'],
  2135.  
  2136. data: function () {
  2137. return {
  2138. itemOnly: hasValue(this.showItemOnly) ? this.showItemOnly : false
  2139. }
  2140. },
  2141.  
  2142. computed: {
  2143. showPrice () {
  2144. return this.isItemSellable() && this.item.price > 0;
  2145. },
  2146.  
  2147. showPhysicalMerch () {
  2148. var physicalMerch = this.isItemSellable() && this.item.unlock === 'physical';
  2149. return physicalMerch;
  2150. },
  2151. },
  2152.  
  2153. mounted() {
  2154. this.renderItem();
  2155. this.itemHightlightedOrder();
  2156. },
  2157. methods: {
  2158. isItemSellable: function () {
  2159. return !this.itemOnly && vueData.equip.mode == vueData.equip.equipModes.shop;
  2160. },
  2161.  
  2162. renderItem: function () {
  2163. extern.renderItemToCanvas(this.item, this.$refs.itemCanvas);
  2164. },
  2165.  
  2166. highlightSelected: function () {
  2167. return this.isSelected ? 'highlight' : '';
  2168. },
  2169.  
  2170. onClick: function () {
  2171. this.$emit('item-selected', this.item);
  2172. },
  2173. itemHightlightedOrder: function() {
  2174. return this.$refs.eggItemInvetory.classList.contains('highlight') ? this.$refs.eggItemInvetory.style.order='-1' : null;
  2175. },
  2176. },
  2177.  
  2178. watch: {
  2179. item: function (val) {
  2180. this.renderItem();
  2181. }
  2182. }
  2183. };
  2184. </script><script id="gold-chicken-template" type="text/x-template">
  2185. <div>
  2186. <div class="f_row fullwidth">
  2187.  
  2188. <div id="popupInnards" class="box_blue3 roundme_sm f_col center_cont f_justify_start ss_marginright_lg">
  2189. <h2 class="text_white shadow_blue4 nospace margintop_xl">{{ loc.p_chicken_goldchicken }}</h2>
  2190. <p class="nospace"><strong>{{ loc.p_chicken_goldchicken_price }}</strong></p>
  2191. <p align="center"><img src="./img/chicken_shadow.png" class="chicken_popup_image"></p>
  2192. <div class="box_light roundme_sm fullwidth">
  2193. <ul>
  2194. <li> {{ loc.p_chicken_goldfeature1 }} </li>
  2195. <li> {{ loc.p_chicken_goldfeature2 }} </li>
  2196. <li v-html="loc.p_chicken_goldfeature3"></li>
  2197. <li> {{ loc.p_chicken_goldfeature4 }} </li>
  2198. </ul>
  2199. </div>
  2200. <button class="ss_button btn_green bevel_green btn_sm center_h" @click="onChickenClick">{{ loc.p_chicken_goldbutton }}</button>
  2201. </div>
  2202.  
  2203. <div id="popupInnards" class="box_blue3 roundme_sm f_col center_cont f_justify_start">
  2204. <h2 class="text_white shadow_blue4 nospace margintop_xl">{{ loc.p_chicken_nugget }}</h2>
  2205. <p class="nospace"><strong>{{ loc.p_chicken_nugget_price }}</strong></p>
  2206. <p align="center"><img src="./img/nugget_shadow.png" class="chicken_popup_image"></p>
  2207. <div class="box_light roundme_sm fullwidth">
  2208. <ul>
  2209. <li>{{ loc.p_chicken_nuggetfeature1 }}</li>
  2210. <li> {{ loc.p_chicken_nuggetfeature2 }} </li>
  2211. <li v-html="loc.p_chicken_nuggetfeature3"></li>
  2212. <li> {{ loc.p_chicken_nuggetfeature4 }} </li>
  2213. </ul>
  2214. </div>
  2215.  
  2216. <button class="ss_button btn_green bevel_green btn_sm center_h" @click="onNuggetClick">{{ loc.p_chicken_nuggetbutton }}</button>
  2217. </div>
  2218. </div>
  2219. <div id="btn_horizontal" class="f_center">
  2220. <button @click="onCloseClick()" class="ss_button btn_red bevel_red btn_sm">{{ loc.cancel }}</button>
  2221. </div>
  2222. </div>
  2223. </script>
  2224.  
  2225. <script>
  2226. var comp_gold_chicken_popup = {
  2227. template: '#gold-chicken-template',
  2228. props: ['loc'],
  2229. methods: {
  2230. onCloseClick: function () {
  2231. this.$parent.close();
  2232. vueApp.playSound('./sound/ui/ui_popupclose.mp3');
  2233. },
  2234. onChickenClick: function () {
  2235. document.exitPointerLock();
  2236. window.onkeydown = null;
  2237. window.onkeyup = null;
  2238. this.$parent.toggle();
  2239. extern.buyGoldenChicken();
  2240. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  2241. },
  2242.  
  2243. onNuggetClick: function () {
  2244. this.$parent.hide();
  2245. extern.startChickenNugget();
  2246. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  2247. }
  2248. }
  2249. };
  2250. </script><script id="chicken-nugget-template" type="text/x-template">
  2251. <div id="popupInnards" class="box_dark roundme_sm fullwidth f_col">
  2252.  
  2253. <h3 class="nospace center_cont">{{ loc.p_nugget_instruction }}</h3>
  2254.  
  2255. <iframe id="miniGameFrame" ref="miniGameFrame" src="about:blank" frameBorder="0" class="roundme_lg" ></iframe>
  2256.  
  2257. <p align="center">
  2258. <button id="gotNuggetOK" v-show="isMiniGameComplete" @click="onGotNugget" class="ss_button btn_shiny clickme invisible">{{ loc.p_nugget_button }}</button>
  2259. </p>
  2260.  
  2261. <div class="center_cont">
  2262. <div id="chickenNuggetAdContainer" ref="chickenNuggetAdContainer" style="display: block; pointer-events: all;"></div>
  2263. </div>
  2264.  
  2265. </div>
  2266. </script>
  2267.  
  2268. <script>
  2269. var comp_chicken_nugget_popup = {
  2270. template: '#chicken-nugget-template',
  2271. props: ['loc'],
  2272.  
  2273. data: function () {
  2274. return {
  2275. isMiniGameComplete: false
  2276. }
  2277. },
  2278.  
  2279. methods: {
  2280. placeBannerAdTag: function (tagEl) {
  2281. this.$refs.chickenNuggetAdContainer.appendChild(tagEl);
  2282. },
  2283.  
  2284. loadMiniGame: function () {
  2285. this.isMiniGameComplete = false;
  2286. this.$refs.miniGameFrame.src = "app_nugget/index.html";
  2287.  
  2288. // The ad tags are outside of the Vue app; manipulate the DOM directly
  2289. this.$refs.chickenNuggetAdContainer.appendChild(vueApp.$options.multisizeAdTag);
  2290. extern.showBannerAd(vueApp.$options.multisizeAdTag.id);
  2291. },
  2292.  
  2293. unloadMiniGame: function () {
  2294. this.$refs.miniGameFrame.src = "about:blank";
  2295. },
  2296.  
  2297. onGotNugget: function () {
  2298. this.$parent.hide();
  2299. this.unloadMiniGame();
  2300. extern.checkUpgrade();
  2301. },
  2302.  
  2303. onMiniGameCompleted: function () {
  2304. this.isMiniGameComplete = true;
  2305. }
  2306. }
  2307. };
  2308. </script>
  2309. <script id="home-screen-template" type="text/x-template">
  2310. <div>
  2311.  
  2312. <house-ad-big id="big-house-ad" :useAd="ui.houseAds.big" @big-house-ad-closed="onBigHouseAdClosed"></house-ad-big>
  2313.  
  2314. <div id="mainHead">
  2315. <streamer-panel id="twitch_panel" :streams="twitchStreams" :title="loc.twitch_title" :viewers="loc.twitch_viewers" icon="ico_twitch"></streamer-panel>
  2316. <!-- <streamer-panel id="youtube_panel" :streams="youtubeStreams" :title="loc.youtube_title" :viewers="loc.youtube_viewers" icon="ico_youtube"></streamer-panel> -->
  2317. </div>
  2318.  
  2319. <div id="mainLayout">
  2320. <account-panel id="account_panel" ref="accountPanel" :loc="loc" :selected-language-code="currentLanguageCode" :eggs="eggs" :languages="languages" :show-corner-buttons="ui.showCornerButtons" :show-bottom="true" :photo-url="photoUrl" :is-anonymous="isAnonymous" :is-of-age="isOfAge" :show-targeted-ads="showTargetedAds" :ui="ui" @sign-in-clicked="onSignInClicked" @sign-out-clicked="onSignOutClicked"></account-panel>
  2321.  
  2322. <div id="logo">
  2323. <a href="https://www.shellshock.io" @click="playSound('./sound/ui/ui_click.mp3')"><img src="img/logo.png"></a>
  2324. </div>
  2325.  
  2326. <div id="panel_front_play">
  2327. <play-panel id="play_game" ref="playPanel" :loc="loc" :player-name="playerName" :game-types="gameTypes" :current-game-type="currentGameType" :server-list="serverList" :current-server-id="currentServerId" :home="home" @playerNameChanged="onPlayerNameChanged"></play-panel>
  2328. <stats-panel id="stats_panel" :loc="loc" :kills="kills" :deaths="deaths" :kdr="kdr" :streak="streak"></stats-panel>
  2329. </div>
  2330.  
  2331. <div id="panel_front_egg">
  2332. <weapon-select-panel id="weapon_select" :current-class="classIdx"></weapon-select-panel>
  2333. <button class="ss_button btn_md btn_yolk bevel_yolk" @click="onEquipClicked">{{ loc.eq_equipment }}</button>
  2334. </div>
  2335.  
  2336. <div id="panel_front_news">
  2337. <div id="news_feed" class="front_panel roundme_md">
  2338. <div id="news_mask"></div>
  2339. <h3 class="nospace">{{ loc.home_latestnews }}</h3>
  2340. <newsfeed-panel id="news_scroll" ref="newsScroll" :current-language-code="currentLanguageCode"></newsfeed-panel>
  2341. </div>
  2342. <house-ad-small id="banner-ad" :useAd="ui.houseAds.small"></house-ad-small>
  2343. </div>
  2344. </div>
  2345.  
  2346. <div id="mainFooter">
  2347. <chicken-panel id="chicken_panel" :loc="loc" :is-upgraded="isUpgraded"></chicken-panel>
  2348. <footer-links-panel id="footer_links_panel" :loc="loc"></footer-links-panel>
  2349. <social-panel id="social_panel"></social-panel>
  2350. </div>
  2351.  
  2352. <!-- Popup: Firebase Sign In -->
  2353. <large-popup id="firebaseSignInPopup" ref="firebaseSignInPopup" :overlay-close="false">
  2354. <template slot="content">
  2355. <h1 class="nospace">{{ loc.p_signin_head }}</h1>
  2356. <div id="firebaseui-auth-container"></div>
  2357. <div id="btn_horizontal" class="f_center">
  2358. <button @click="onSignInCancelClicked()" class="ss_button btn_red bevel_red btn_sm">{{ loc.cancel }}</button>
  2359. </div>
  2360. </template>
  2361. </large-popup>
  2362.  
  2363. <!-- Popup: Check Email -->
  2364. <small-popup id="checkEmailPopup" ref="checkEmailPopup" :hide-cancel="true">
  2365. <template slot="header">{{ loc.p_check_email_title }}</template>
  2366. <template slot="content">
  2367. <p>{{ loc.p_check_email_text1 }}:</p>
  2368. <h5 class="nospace center_cont">{{ maskedEmail }}</h5>
  2369. <p class="ss_marginbottom">{{ loc.p_check_email_text2 }}</p>
  2370. </template>
  2371. <template slot="confirm">{{ loc.ok }}</template>
  2372. </small-popup>
  2373.  
  2374. <!-- Popup: Resend Email -->
  2375. <small-popup id="resendEmailPopup" ref="resendEmailPopup" @popup-confirm="onResendEmailClicked">
  2376. <template slot="header">{{ loc.p_resend_email_title }}</template>
  2377. <template slot="content">
  2378. <p>{{ loc.p_resend_email_text1 }}:</p>
  2379. <h5 class="nospace center_cont">{{ maskedEmail }}</h5>
  2380. <p class="ss_marginbottom">{{ loc.p_resend_email_text2 }}</p>
  2381. </template>
  2382. <template slot="cancel">{{ loc.ok }}</template>
  2383. <template slot="confirm">{{ loc.p_resend_email_resend }}</template>
  2384. </small-popup>
  2385.  
  2386. </div>
  2387. </script>
  2388.  
  2389. <script id="create-private-game-template" type="text/x-template">
  2390. <div>
  2391. <h1 class="roundme_sm">{{ loc.p_privatematch_title }}</h1>
  2392.  
  2393. <div class="box_blue2 roundme_sm fullwidth">
  2394. <div id="popupInnards" class="fullwidth f_row f_spaced">
  2395.  
  2396. <div id="private_left" class="f_col f_start">
  2397. <h3 class="center_cont fullwidth">{{ loc.p_privatematch_gametype }}</h3>
  2398. <select name="gameType" v-model="pickedGameType" class="ss_select fullwidth" @click="playSound('./sound/ui/ui_click.mp3')" @change="playSound('./sound/ui/ui_onchange.mp3')">
  2399. <option v-for="g in gameTypes" v-bind:value="g.value">{{ loc[g.locKey] }}</option>
  2400. </select>
  2401. <button class="ss_button button_blue bevel_blue fullwidth" @click="onServerClick">{{ loc.server }}: {{ loc[serverLocKey] }}</button>
  2402.  
  2403. <button name="play" @click="onPlayClick" class="ss_button btn_big fullwidth btn_green bevel_green btn_sm"><i class="fa fa-play fa-sm"></i> {{ loc.p_privatematch_create }}</button>
  2404. <!-- Player limit is not in place yet
  2405. <h3 class="nospace">{{ loc.p_privatematch_players }}</h3>
  2406.  
  2407. <div id="player_selector">
  2408. <img src="./img/ico_arrowLeft.png" class="numberArrow">
  2409. <input type="text" v-model class="ss_field fld_number">
  2410. <img src="./img/ico_arrowRight.png" class="numberArrow">
  2411. </div> -->
  2412. </div>
  2413.  
  2414. <div class="f_col j_start">
  2415. <h3 class="ss_marginleft_lg center_cont">{{ loc.p_privatematch_selectmap }}</h3>
  2416.  
  2417. <div id="private_maps" class="ss_marginleft_lg roundme_md">
  2418. <img :src="mapImgPath" id="mapThumb" class="roundme_sm">
  2419. <div id="mapNav">
  2420. <button id="mapLeft" @click="onMapChange(-1)" class="clickme"> </button>
  2421. <h5 id="mapText">
  2422. {{ loc[mapLocKey].name }}
  2423. <span class="map_playercount shadow_grey roundme_sm">
  2424. <img src="img/ico_eggColour_normal.png">
  2425. <span class="ss_marginbottom_xs ss_marginright_xs">x</span>
  2426. <span>{{loc[mapLocKey].suggested_player_limit}}</span>
  2427. </span>
  2428. </h5>
  2429.  
  2430. <button id="mapRight" @click="onMapChange(1)" class="clickme"> </button>
  2431. </div>
  2432. </div>
  2433.  
  2434. </div>
  2435. </div>
  2436.  
  2437. <div id="btn_horizontal" class="f_center nospace">
  2438. <button @click="onCloseClick()" class="ss_button btn_red bevel_red btn_sm">{{ loc.cancel }}</button>
  2439. </div>
  2440. </div>
  2441. </div>
  2442. </script>
  2443.  
  2444. <script>
  2445. var comp_create_private_game_popup = {
  2446. template: '#create-private-game-template',
  2447. props: ['loc', 'serverLocKey', 'mapImgBasePath'],
  2448.  
  2449. data: function () {
  2450. return {
  2451. showingServerList: false,
  2452. pickedGameType: 0,
  2453. gameTypes: vueData.gameTypes,
  2454. mapIdx: 0,
  2455. mapImgPath: this.mapImgBasePath + vueData.maps[0].img,
  2456. mapLocKey: vueData.maps[0].locKey
  2457. }
  2458. },
  2459.  
  2460. methods: {
  2461. playSound (sound) {
  2462. vueApp.playSound(sound);
  2463. },
  2464.  
  2465. onCloseClick: function () {
  2466. this.$parent.close();
  2467. vueApp.playSound('./sound/ui/ui_popupclose.mp3');
  2468. },
  2469.  
  2470. onServerClick: function () {
  2471. this.showingServerList = true;
  2472. this.$parent.toggle();
  2473. vueApp.$refs.homeScreen.$refs.playPanel.$refs.pickServerPopup.toggle();
  2474. vueApp.playSound('./sound/ui/ui_click.mp3');
  2475. },
  2476.  
  2477. onMapChange: function(dir) {
  2478. this.mapIdx = ((this.mapIdx + dir) + vueData.maps.length) % vueData.maps.length;
  2479. this.mapImgPath = this.mapImgBasePath + vueData.maps[this.mapIdx].img;
  2480. this.mapLocKey = vueData.maps[this.mapIdx].locKey;
  2481.  
  2482. console.log(this.mapIdx);
  2483.  
  2484. vueApp.playSound('./sound/ui/ui_onchange.mp3');
  2485. },
  2486.  
  2487. onPlayClick: function () {
  2488. this.$parent.toggle();
  2489.  
  2490. extern.play({
  2491. playType: vueData.playTypes.createPrivate,
  2492. gameType: this.pickedGameType,
  2493. mapIdx: this.mapIdx,
  2494. playerName: vueData.playerName
  2495. });
  2496.  
  2497. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  2498. }
  2499. }
  2500. };
  2501. </script><script id="account-panel-template" type="text/x-template">
  2502. <div>
  2503. <div id="account_top">
  2504. <input v-if="isAnonymous" type="image" src="img/attention_indicator.png" v-show="showCornerButtons" @click="onAnonWarningClick" class="account_icon roundme_sm attention_btn" v-bind:title="loc['account_title_shop']">
  2505. <div class="account_eggs roundme_sm clickme" @click="onEggStoreClick" v-bind:title="loc['account_title_eggshop']">
  2506. <img src="img/ico_goldenEgg.png" class="egg_icon">
  2507. <span class="egg_count shadow_blue2_micro">{{ eggs }}</span>
  2508. </div>
  2509. <!-- <input type="image" src="img/ico_nav_leaderboards.png" class="account_icon roundme_sm"> -->
  2510. <input type="image" src="img/ico_nav_shop.png" v-show="showCornerButtons" @click="itemStoreClick" class="account_icon roundme_sm" v-bind:title="loc['account_title_shop']">
  2511. <input type="image" src="img/ico_nav_help.png" v-show="showCornerButtons" @click="onHelpClick" class="account_icon roundme_sm" v-bind:title="loc['account_title_faq']">
  2512. <input type="image" src="img/ico_nav_share.png" v-show="showShareLinkButton" @click="onShareLinkClick" class="account_icon roundme_sm" v-bind:title="loc['account_title_invite']">
  2513. <input type="image" src="img/ico_nav_settings.png" v-show="showCornerButtons" @click="onSettingsClick" class="account_icon roundme_sm" v-bind:title="loc['account_title_settings']">
  2514. <input type="image" src="img/ico_nav_fullscreen.png" v-show="showCornerButtons" @click="onFullscreenClick" class="account_icon roundme_sm" v-bind:title="loc['account_title_fullscreen']">
  2515. </div>
  2516.  
  2517. <div id="account_bottom" v-show="showBottom">
  2518. <language-selector :languages="languages" :loc="loc" :selectedLanguageCode="selectedLanguageCode"></language-selector>
  2519.  
  2520. <button id="signInButton" v-show="(isAnonymous && showSignIn)" @click="onSignInClicked" class="ss_button btn_yolk bevel_yolk">{{ loc.sign_in }}</button>
  2521. <button id="signOutButton" v-show="!isAnonymous" @click="onSignOutClicked" class="ss_button btn_yolk bevel_yolk">{{ loc.sign_out }}</button>
  2522. <div id="player_photo" v-show="photoUrl !== null && photoUrl !== undefined && photoUrl !== '' && ! isAnonymous">
  2523. <img :src="photoUrl" class="roundme_sm bevel_blue"/>
  2524. </div>
  2525. </div>
  2526. </div>
  2527.  
  2528. </script>
  2529.  
  2530. <script>
  2531. var comp_account_panel = {
  2532. template: '#account-panel-template',
  2533. components: {
  2534. 'language-selector': comp_language_selector
  2535. },
  2536. props: ['loc', 'eggs', 'languages', 'selectedLanguageCode', 'showBottom', 'photoUrl', 'isAnonymous', 'isOfAge', 'showTargetedAds', 'showCornerButtons', 'ui'],
  2537.  
  2538. data: function () {
  2539. return {
  2540. languageCode: this.selectedLanguageCode
  2541. }
  2542. },
  2543.  
  2544. methods: {
  2545. onEggStoreClick: function () {
  2546. vueApp.showEggStorePopup();
  2547. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  2548. },
  2549. itemStoreClick: function() {
  2550. if (extern.inGame) {
  2551. vueApp.$refs.gameScreen.hideGameMenu();
  2552. extern.openEquipInGame();
  2553. vueApp.switchToEquipUi();
  2554. }
  2555. else {
  2556. vueApp.switchToEquipUi();
  2557. }
  2558. vueApp.$refs.equipScreen.switchToShop();
  2559. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  2560. },
  2561. onHelpClick: function () {
  2562. vueApp.showHelpPopup();
  2563. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  2564. },
  2565.  
  2566. onSettingsClick: function () {
  2567. ga('send', 'event', 'open settings');
  2568. vueApp.showSettingsPopup();
  2569. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  2570. },
  2571.  
  2572. onFullscreenClick: function () {
  2573. extern.toggleFullscreen();
  2574. vueApp.playSound('./sound/ui/ui_click.mp3');
  2575. },
  2576.  
  2577. onSignInClicked: function () {
  2578. vueApp.setDarkOverlay(true);
  2579. this.$emit('sign-in-clicked');
  2580. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  2581. },
  2582.  
  2583. onSignOutClicked: function () {
  2584. vueApp.setDarkOverlay(true);
  2585. this.$emit('sign-out-clicked');
  2586. vueApp.playSound('./sound/ui/ui_reset.mp3');
  2587. },
  2588.  
  2589. onShareLinkClick: function () {
  2590. extern.inviteFriends();
  2591. },
  2592.  
  2593. onAnonWarningClick: function() {
  2594. vueApp.showAttentionPopup();
  2595. }
  2596. },
  2597.  
  2598. computed: {
  2599. showSignIn: function () {
  2600. if (!isFromEU) {
  2601. return true;
  2602. }
  2603.  
  2604. return isFromEU && this.isOfAge && this.showTargetedAds;
  2605. },
  2606.  
  2607. showShareLinkButton: function () {
  2608. return this.showCornerButtons && (this.ui.showScreen === this.ui.screens.game);
  2609. }
  2610. }
  2611. };
  2612. </script>
  2613. <script id="streamer-panel-template" type="text/x-template">
  2614. <div class="panel_streamer noscroll">
  2615. <div id="stream_mask"></div>
  2616. <h1 class="stream_head roundme_sm" :class="icon">{{ title }}</h1>
  2617. <div id="stream_scroll" class="v_scroll" v-show="show">
  2618. <div class="stream_item roundme_sm" v-for="s in streams">
  2619. <a :href="s.link" target="_blank" @click="playSound('./sound/ui/ui_click.mp3')">
  2620. <img :src="s.image" class="stream_img roundme_sm"> {{ s.name }}
  2621. <p class="stream_viewers">{{ s.viewers }} {{ viewers }}</p>
  2622. </a>
  2623. </div>
  2624. </div>
  2625. </div>
  2626. </script>
  2627.  
  2628. <script>
  2629. var comp_streamer_panel = {
  2630. template: '#streamer-panel-template',
  2631. props: ['streams', 'title', 'viewers', 'icon'],
  2632. methods: {
  2633. playSound (sound) {
  2634. vueApp.playSound(sound);
  2635. }
  2636. },
  2637. computed: {
  2638. show: function() {
  2639. if (!this.streams) {
  2640. return false;
  2641. }
  2642.  
  2643. return this.streams.length > 0;
  2644. }
  2645. }
  2646. };
  2647. </script><template id="stats_panel_template" type="text/x-template">
  2648. <div class="front_panel roundme_md">
  2649. <h3 class="nospace">{{ loc.home_stats }}</h3>
  2650. <div id="stat_item" class="roundme_sm">
  2651. <h4>{{ loc.kills.toUpperCase() }}</h4>
  2652. <div class="stat_stat">{{ kills }}</div>
  2653. </div>
  2654.  
  2655. <div id="stat_item" class="roundme_sm">
  2656. <h4>{{ loc.deaths.toUpperCase() }}</h4>
  2657. <div class="stat_stat">{{ deaths }}</div>
  2658. </div>
  2659.  
  2660. <div id="stat_item" class="roundme_sm">
  2661. <h4>{{ loc.kdr.toUpperCase() }}</h4>
  2662. <div class="stat_stat">{{ kdr }}</div>
  2663. </div>
  2664.  
  2665. <div id="stat_item" class="roundme_sm">
  2666. <h4>{{ loc.streak.toUpperCase() }}</h4>
  2667. <div class="stat_stat">{{ streak }}</div>
  2668. </div>
  2669. </div>
  2670. </template>
  2671.  
  2672. <script>
  2673. var comp_stats_panel = {
  2674. template: '#stats_panel_template',
  2675. props: ['loc', 'kills', 'deaths', 'kdr', 'streak'],
  2676. };
  2677.  
  2678. </script>
  2679.  
  2680. <script id="play-panel-template" type="text/x-template">
  2681. <div>
  2682. <div class="front_panel roundme_md">
  2683.  
  2684. <input name="name" :value="playerName" v-bind:placeholder="loc.play_enter_name" @change="onNameChange($event)" v-on:keyup="onPlayerNameKeyUp($event)" class="ss_field fullwidth"><br>
  2685. <select name="gameType" v-model="pickedGameType" class="ss_select fullwidth" @change="onGameTypeChange($event)">
  2686. <option v-for="g in gameTypes" v-bind:value="g.value">{{ loc[g.locKey] }}</option>
  2687. </select><br>
  2688. <button name="server" @click="onPickServerButtonClick" class="ss_button btn_blue bevel_blue fullwidth">{{ loc.server }}: {{ loc[serverLocKey] }}</button><br>
  2689. <button name="play" @click="onPlayButtonClick" class="ss_button btn_big btn_green bevel_green fullwidth nospace"><i class="fa fa-play fa-sm"></i> {{ loc.home_play }}</button>
  2690.  
  2691. <h3>{{ loc.home_privategames }}</h3>
  2692.  
  2693. <div id="btn_horizontal" class="nospace">
  2694. <button name="create" @click="onCreatePrivateGameClick" class="ss_button btn_sm btn_blue bevel_blue">{{ loc.home_create }}</button>&nbsp;
  2695. <button name="join" @click="onJoinPrivateGameClick" class="ss_button btn_sm btn_blue bevel_blue">{{ loc.home_join }}</button>
  2696. </div>
  2697.  
  2698. </div>
  2699.  
  2700. <!-- Popup: Pick Server -->
  2701. <large-popup id="pickServerPopup" ref="pickServerPopup" @popup-closed="onPickServerPopupClosed">
  2702. <template slot="header">{{ loc.server }}</template>
  2703. <template slot="content">
  2704. <server-list-popup id="server_list_popup" ref="serverListPopup" v-if="(serverList.length > 0)" :loc="loc" :servers="serverList" :picked-server-id="currentServerId" @server-picked="onServerPicked"></server-list-popup>
  2705. </template>
  2706. </large-popup>
  2707.  
  2708. <!-- Popup: Create Private Game -->
  2709. <large-popup id="createPrivateGamePopup" ref="createPrivateGamePopup">
  2710. <template slot="content">
  2711. <create-private-game-popup id="createPrivateGame" ref="createPrivateGame" :loc="loc" :server-loc-key="serverLocKey" map-img-base-path="./img/maps/"></create-private-game-popup>
  2712. </template>
  2713. </large-popup>
  2714.  
  2715. <!-- Popup: Join Private Game -->
  2716. <small-popup id="joinPrivateGamePopup" ref="joinPrivateGamePopup" :popup-model="home.joinPrivateGamePopup" @popup-confirm="onJoinConfirmed">
  2717. <template slot="header">{{ loc.p_game_code_title }}</template>
  2718. <template slot="content">
  2719. <div class="error_text shadow_red" v-show="home.joinPrivateGamePopup.showInvalidCodeMsg">{{ loc.p_game_code_blank }}</div>
  2720. <p><input type="text" class="ss_field ss_margintop ss_marginbottom fullwidth center_cont" v-model="home.joinPrivateGamePopup.code" v-bind:placeholder="loc.p_game_code_enter" v-on:keyup.enter="onJoinConfirmed"></p>
  2721. </template>
  2722. <template slot="cancel">{{ loc.cancel }}</template>
  2723. <template slot="confirm">{{ loc.confirm }}</template>
  2724. </small-popup>
  2725. </div>
  2726. </script>
  2727.  
  2728. <script id="server-list-template" type="text/x-template">
  2729. <div>
  2730. <h1 class="roundme_sm">{{ loc.p_servers_title }}</h1>
  2731. <div v-for="s in servers" :key="s.id">
  2732. <div id="server_list_item">
  2733. <input type="radio" :id="('rb_' + s.id)" name="pickServer" v-bind:value="s.id" v-model="serverId" @click="playSound('./sound/ui/ui_onchange.mp3')">
  2734. <label :for="('rb_' + s.id)" class="serverName">{{ loc[s.locKey] }} </label>
  2735. <label :for="('rb_' + s.id)" class="serverPingWrap roundme_sm">
  2736. <span class="pingBar" :class="barColorClass(s)" :style="barStyle(s)"></span>
  2737. </label>
  2738. <label :for="('rb_' + s.id)" class="serverPingNumber ss_marginleft_lg"> {{ s.ping }}ms</label>
  2739. </div>
  2740. </div>
  2741. <div id="btn_horizontal" class="f_center">
  2742. <button @click="onCancelClick()" class="ss_button btn_red bevel_red btn_sm">{{ loc.cancel }}</button>
  2743. <button @click="onConfirmClick()" class="ss_button btn_green bevel_green btn_sm">{{ loc.ok }}</button>
  2744. </div>
  2745. </div>
  2746. </script>
  2747.  
  2748. <script>
  2749. var comp_server_list_popup = {
  2750. template: '#server-list-template',
  2751. props: ['loc', 'servers', 'pickedServerId'],
  2752.  
  2753. data: function () {
  2754. return {
  2755. colorClasses: ['greenPing', 'yellowPing','orangePing', 'redPing'],
  2756. serverId: this.pickedServerId
  2757. }
  2758. },
  2759.  
  2760. methods: {
  2761. playSound (sound) {
  2762. vueApp.playSound(sound);
  2763. },
  2764.  
  2765. barColorClass: function (server) {
  2766. var colorIdx = Math.min(3, Math.floor(server.ping / 100));
  2767. return this.colorClasses[colorIdx];
  2768. },
  2769.  
  2770. barStyle: function (server) {
  2771. return {
  2772. width: Math.min(10, Math.max(0, server.ping / 100)) + 0.1 + 'em'
  2773. }
  2774. },
  2775.  
  2776. onCancelClick: function () {
  2777. this.serverId = this.pickedServerId;
  2778. this.$parent.close();
  2779. vueApp.playSound('./sound/ui/ui_popupclose.mp3');
  2780. },
  2781.  
  2782. onConfirmClick: function () {
  2783. this.$emit('server-picked', this.serverId);
  2784. this.$parent.close();
  2785. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  2786. }
  2787. }
  2788. };
  2789. </script>
  2790. <script>
  2791. var comp_play_panel = {
  2792. template: '#play-panel-template',
  2793. components: {
  2794. 'create-private-game-popup': comp_create_private_game_popup,
  2795. 'server-list-popup': comp_server_list_popup
  2796. },
  2797.  
  2798. props: ['loc', 'playerName', 'gameTypes', 'currentGameType', 'serverList', 'currentServerId', 'home'],
  2799.  
  2800. data: function() {
  2801. return {
  2802. pickedServerId: null,
  2803. pickedGameType: this.currentGameType
  2804. }
  2805. },
  2806.  
  2807. methods: {
  2808. onPickServerButtonClick: function () {
  2809. this.$refs.pickServerPopup.toggle();
  2810. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  2811. },
  2812.  
  2813. onServerPicked: function (serverId) {
  2814. if (vueData.currentServerId === serverId) { return; }
  2815.  
  2816. vueData.currentServerId = serverId;
  2817. extern.selectServer(vueData.currentServerId);
  2818. vueApp.playSound('./sound/ui/ui_onchange.mp3');
  2819. },
  2820.  
  2821. onPickServerPopupClosed: function () {
  2822. if (this.$refs.createPrivateGame.showingServerList) {
  2823. this.$refs.createPrivateGame.showingServerList = false;
  2824. this.$refs.createPrivateGamePopup.toggle();
  2825. }
  2826. },
  2827.  
  2828. onNameChange: function (event) {
  2829. console.log('name changed to: ' + event.target.value);
  2830. this.$emit('playerNameChanged', event.target.value);
  2831. },
  2832.  
  2833. onPlayerNameKeyUp: function (event) {
  2834. event.target.value = extern.fixStringWidth(event.target.value);
  2835.  
  2836. // Send username to server to start the game!
  2837. if (event.code == "Enter" || event.keyCode == 13) {
  2838. if (vueData.playerName.length > 0) {
  2839. extern.play({
  2840. playType: vueData.playTypes.joinPublic,
  2841. playerName: vueData.playerName
  2842. });
  2843. }
  2844. }
  2845. },
  2846.  
  2847. onGameTypeChange: function (event) {
  2848. extern.selectGameType(event.target.value);
  2849. vueApp.playSound('./sound/ui/ui_onchange.mp3');
  2850. },
  2851.  
  2852. onPlayButtonClick: function () {
  2853. if (!hasValue(this.playerName)) {
  2854. console.log('invalid player name');
  2855. vueApp.showGenericPopup('play_pu_name_title', 'play_pu_name_content', 'ok');
  2856. return;
  2857. }
  2858.  
  2859. vueApp.game.respawnTime = 0;
  2860.  
  2861. extern.play({
  2862. playType: vueData.playTypes.joinPublic,
  2863. gameType: this.pickedGameType,
  2864. playerName: this.playerName,
  2865. mapIdx: -1
  2866. });
  2867.  
  2868. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  2869. },
  2870.  
  2871. onCreatePrivateGameClick: function () {
  2872. this.$refs.createPrivateGamePopup.toggle();
  2873. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  2874. },
  2875.  
  2876. onJoinPrivateGameClick: function () {
  2877. this.showJoinPrivateGamePopup(vueData.home.joinPrivateGamePopup.code);
  2878. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  2879. },
  2880.  
  2881. showJoinPrivateGamePopup: function (showCode) {
  2882. // The popup must be active before it will update; set code after showing
  2883. this.$refs.joinPrivateGamePopup.show();
  2884. vueData.home.joinPrivateGamePopup.code = showCode;
  2885. },
  2886.  
  2887. onJoinConfirmed: function () {
  2888. vueData.home.joinPrivateGamePopup.code = vueData.home.joinPrivateGamePopup.code.replace(parsedUrl.root, '');
  2889. this.$refs.joinPrivateGamePopup.hide();
  2890.  
  2891. extern.play({
  2892. playType: vueData.playTypes.joinPrivate,
  2893. playerName: this.playerName,
  2894. joinCode: vueData.home.joinPrivateGamePopup.code
  2895. });
  2896. }
  2897. },
  2898.  
  2899. computed: {
  2900. serverLocKey: function () {
  2901. if (!hasValue(this.serverList) || this.serverList.length === 0) {
  2902. return '';
  2903. }
  2904.  
  2905. var server = this.serverList.find(s => {
  2906. return s.id == vueData.currentServerId;
  2907. });
  2908.  
  2909. return hasValue(server) ? server.locKey : '';
  2910. }
  2911. },
  2912.  
  2913. watch: {
  2914. currentGameType: function (val) {
  2915. this.pickedGameType = val;
  2916. }
  2917. }
  2918. };
  2919. </script><template id="weaponselect_panel_template" type="text/x-template">
  2920. <div>
  2921. <img src="img/ico_weapon_assaultRifle.png" class="weapon_img roundme_lg" :class="addSelectedCssClass(charClass.Soldier)" @click="selectClass(charClass.Soldier)">
  2922. <img src="img/ico_weapon_shotgun.png" class="weapon_img roundme_lg" :class="addSelectedCssClass(charClass.Scrambler)" @click="selectClass(charClass.Scrambler)">
  2923. <img src="img/ico_weapon_sniper.png" class="weapon_img roundme_lg" :class="addSelectedCssClass(charClass.Ranger)" @click="selectClass(charClass.Ranger)">
  2924. <img src="img/ico_weapon_rocketLauncher.png" class="weapon_img roundme_lg" :class="addSelectedCssClass(charClass.Eggsploder)" @click="selectClass(charClass.Eggsploder)">
  2925. <img src="img/ico_weapon_SMG.png" class="weapon_img roundme_lg" :class="addSelectedCssClass(charClass.Whipper)" @click="selectClass(charClass.Whipper)">
  2926. <img src="img/ico_weapon_boltAction.png" class="weapon_img roundme_lg" :class="addSelectedCssClass(charClass.Crackshot)" @click="selectClass(charClass.Crackshot)">
  2927. </div>
  2928. </template>
  2929.  
  2930. <script>
  2931. var comp_weapon_select_panel = {
  2932. template: '#weaponselect_panel_template',
  2933. props: ['currentClass'],
  2934.  
  2935. data: function () {
  2936. return {
  2937. charClass: CharClass
  2938. }
  2939. },
  2940.  
  2941. methods: {
  2942. selectClass: function (classIdx) {
  2943. extern.changeClass(classIdx);
  2944. this.$emit('changed-class', classIdx);
  2945. vueApp.playSound('./sound/ui/ui_click.mp3');
  2946. },
  2947.  
  2948. addSelectedCssClass: function (classIdx) {
  2949. return (this.currentClass === classIdx)
  2950. ? 'weapon_selected'
  2951. : '';
  2952. }
  2953. }
  2954. };
  2955. </script>
  2956. <script id="newsfeed-panel-template" type="text/x-template">
  2957. <div class="v_scroll">
  2958. <div v-for="item in localizedItems" @click="onItemClicked(item)" class="news_item roundme_md" :class="applyClickClass(item)">
  2959. <img :src="('img/newsItems/' + item.image)" class="news_img roundme_sm">
  2960. <p>{{ item.msg }}</p>
  2961. </div>
  2962. </div>
  2963. </script>
  2964.  
  2965. <script>
  2966. var comp_newsfeed_panel = {
  2967. template: '#newsfeed-panel-template',
  2968. props: ['currentLanguageCode'],
  2969.  
  2970. data: function () {
  2971. return {
  2972. items: [],
  2973. localizedItems: []
  2974. }
  2975. },
  2976.  
  2977. mounted: function () {
  2978. var outer = this;
  2979.  
  2980. fetch('newsItems.json')
  2981. .then(function(response) {
  2982. response.json()
  2983. .then(function(parsedItemList) {
  2984. outer.items = parsedItemList;
  2985. outer.localizeItems();
  2986. });
  2987. });
  2988. },
  2989.  
  2990. methods: {
  2991. localizeItems: function () {
  2992. let locItemList = [];
  2993. const lang = 'en';
  2994. this.items.forEach( (item) => {
  2995. var locEntry = item.loc.find((l) => {
  2996. // Since we have no localization for news items only display en
  2997. // return l.code === this.currentLanguageCode;
  2998. return l.code === lang;
  2999. });
  3000.  
  3001. item.msg = hasValue(locEntry) ? locEntry.msg : '';
  3002.  
  3003. locItemList.push(item);
  3004. });
  3005.  
  3006. this.localizedItems = locItemList;
  3007. },
  3008.  
  3009. onItemClicked: function(item) {
  3010. extern.clickedHouseLink(item);
  3011. vueApp.playSound('./sound/ui/ui_click.mp3');
  3012. },
  3013.  
  3014. applyClickClass: function (item) {
  3015. return extern.hasHouseLink(item) ? 'clickme' : '';
  3016. }
  3017. },
  3018.  
  3019. watch: {
  3020. // Rebuild the localized item array when the current language code changes
  3021. currentLanguageCode: function (newCode) {
  3022. this.localizeItems();
  3023. }
  3024. }
  3025. };
  3026. </script><script id="chicken-panel-template" type="text/x-template">
  3027. <div id="showBuyPassDialogButton">
  3028. <img src="img/ico_chickenBadge.png" v-show="isUpgraded">
  3029. <div v-show="!isUpgraded">
  3030. <img src="img/anim_chicken.gif" @click="onChickenClick" class="clickme">
  3031.  
  3032. <div id="buyPassChickenSpeech">
  3033. <img src="img/speechtail.png" class="buyPassChickenSpeechTail">
  3034. <span v-html="loc.chicken_cta"></span>
  3035. </div>
  3036. </div>
  3037. </div>
  3038. </script>
  3039.  
  3040. <script>
  3041. var comp_chicken_panel = {
  3042. template: '#chicken-panel-template',
  3043. props: ['loc', 'isUpgraded'],
  3044.  
  3045. methods: {
  3046. onChickenClick: function () {
  3047. vueApp.playSound('./sound/ui/ui_chicken.mp3');
  3048. vueApp.showGoldChickenPopup();
  3049. }
  3050. }
  3051. };
  3052. </script><script id="footer-links-panel-template" type="text/x-template">
  3053. <div class="center_h">
  3054. <a @click="onChangelogClicked" class="clickme">{{ version }}</a> |
  3055. <a href="https://shell-shockers.myshopify.com/collections/all" target="_blank" @click="playSound('./sound/ui/ui_click.mp3')">{{ loc.footer_merchandise }}</a> |
  3056. <a href="https://www.bluewizard.com/privacypolicy" target="_blank" @click="playSound('./sound/ui/ui_click.mp3')">{{ loc.footer_privacypolicy }}</a> |
  3057. <a href="https://bluewizard.com/terms/" target="_blank" @click="playSound('./sound/ui/ui_click.mp3')">{{ loc.footer_termsofservice }}</a> |
  3058. <a href="https://www.bluewizard.com" target="_blank" @click="playSound('./sound/ui/ui_click.mp3')">&copy; 2019 {{ loc.footer_bluewizard }}</a>
  3059. </div>
  3060. </script>
  3061.  
  3062. <script>
  3063. var comp_footer_links_panel = {
  3064. template: '#footer-links-panel-template',
  3065. props: ['loc'],
  3066.  
  3067. data: function () {
  3068. return {
  3069. version: version
  3070. }
  3071. },
  3072.  
  3073. methods: {
  3074. onChangelogClicked: function () {
  3075. vueApp.showChangelogPopup();
  3076. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  3077. },
  3078. playSound (sound) {
  3079. vueApp.playSound(sound);
  3080. }
  3081. }
  3082. };
  3083. </script>
  3084. <script id="social-panel-template" type="text/x-template">
  3085. <div class="social_icons roundme_sm">
  3086. <a href="http://eepurl.com/dFPPwb" target="_blank"><img src="img/ico_social_newsletter.png" class="social_icon" @click="playSound('./sound/ui/ui_click.mp3')"></a>
  3087. <a href="https://discord.gg/bluewizard" target="_blank"><img src="img/ico_social_discord.png" class="social_icon" @click="playSound('./sound/ui/ui_click.mp3')"></a>
  3088. <a href="https://www.facebook.com/ShellShockersGame" target="_blank"><img src="img/ico_social_facebook.png" class="social_icon" @click="playSound('./sound/ui/ui_click.mp3')"></a>
  3089. <a href="https://twitter.com/eggcombat" target="_blank"><img src="img/ico_social_twitter.png" class="social_icon" @click="playSound('./sound/ui/ui_click.mp3')"></a>
  3090. </div>
  3091. </script>
  3092.  
  3093. <script>
  3094. var comp_social_panel = {
  3095. template: '#social-panel-template',
  3096. methods: {
  3097. playSound (sound) {
  3098. vueApp.playSound(sound);
  3099. }
  3100. }
  3101. };
  3102. </script>
  3103. <script>
  3104. var comp_home_screen = {
  3105. template: '#home-screen-template',
  3106. components: {
  3107. 'streamer-panel': comp_streamer_panel,
  3108. 'stats-panel': comp_stats_panel,
  3109. 'play-panel': comp_play_panel,
  3110. 'weapon-select-panel': comp_weapon_select_panel,
  3111. 'newsfeed-panel': comp_newsfeed_panel,
  3112. 'house-ad-big': comp_house_ad_big,
  3113. 'house-ad-small': comp_house_ad_small,
  3114. 'account-panel': comp_account_panel,
  3115. 'chicken-panel': comp_chicken_panel,
  3116. 'footer-links-panel': comp_footer_links_panel,
  3117. 'social-panel': comp_social_panel
  3118. },
  3119.  
  3120. data: function () {
  3121. return vueData;
  3122. },
  3123.  
  3124. methods: {
  3125. playSound (sound) {
  3126. vueApp.playSound(sound);
  3127. },
  3128.  
  3129. onEquipClicked: function () {
  3130. vueApp.switchToEquipUi();
  3131. vueApp.playSound('./sound/ui/ui_equip.mp3');
  3132. },
  3133.  
  3134. showSignIn: function () {
  3135. this.$refs.firebaseSignInPopup.toggle();
  3136. extern.showSignInDialog();
  3137. },
  3138.  
  3139. onSignInClicked: function () {
  3140. this.showSignIn();
  3141. },
  3142.  
  3143. onSignInCancelClicked: function () {
  3144. this.$refs.firebaseSignInPopup.hide();
  3145. vueApp.playSound('./sound/ui/ui_popupclose.mp3');
  3146. },
  3147.  
  3148. onSignOutClicked: function () {
  3149. extern.signOut();
  3150. },
  3151.  
  3152. onResendEmailClicked: function () {
  3153. extern.sendFirebaseVerificationEmail();
  3154.  
  3155. vueApp.showGenericPopup('verify_email_sent', 'verify_email_instr', 'ok');
  3156. },
  3157.  
  3158. onBigHouseAdClosed: function () {
  3159. console.log('big house ad closed event received');
  3160. this.ui.houseAds.big = null;
  3161. },
  3162.  
  3163. onPlayerNameChanged: function (newName) {
  3164. console.log('play name event handler');
  3165. vueApp.setPlayerName(newName);
  3166. vueApp.playSound('./sound/ui/ui_onchange.mp3');
  3167. }
  3168. }
  3169. };
  3170. </script><script id="equip-screen-template" type="text/x-template">
  3171. <div>
  3172. <div id="equip_wrapper">
  3173.  
  3174. <account-panel id="account_panel" ref="accountPanel" :loc="loc" :eggs="eggs" :show-corner-buttons="ui.showCornerButtons" :ui="ui" :show-bottom="false" :is-anonymous="isAnonymous"></account-panel>
  3175.  
  3176. <div id="equip_box">
  3177.  
  3178. <section id="equip_panel_left" class="equip_panel left_panel">
  3179. <div class="equip_panelhead">
  3180. </div>
  3181. <div id="equip_sidebox" class="roundme_md">
  3182. <equipped-slots id="equip.equipped_slots" ref="equip.equipped_slots" :loc="loc" :primary-item="equip.equippedPrimary" :secondary-item="equip.equippedSecondary" :hat-item="equip.equippedHat" :stamp-item="equip.equippedStamp" @equipped-type-selected="onEquippedTypeSelected"></equipped-slots>
  3183. <color-select id="equip.equipped_slots" ref="colorSelect" :loc="loc" :color-idx="equip.colorIdx" :extra-colors-locked="equip.extraColorsLocked" @color-changed="onColorChanged"></color-select>
  3184. </div>
  3185. <p align="center"><button @click="onRedeemClick" class="ss_button btn_blue1 btn_md bevel_blue">{{ loc.eq_redeem }}</button></p>
  3186. </section>
  3187. <!-- end.left_panel -->
  3188.  
  3189. <section id="equip_panel_middle" class="equip_panel middle_panel">
  3190. <div class="equip_panelhead panel_tabs">
  3191. <button class="ss_bigtab bevel_blue ss_marginright" :class="getButtonToggleClass(equip.equipModes.inventory)" @click="switchToInventory">{{ loc.eq_inventory }}</button>
  3192. <button class="ss_bigtab bevel_blue" :class="getButtonToggleClass(equip.equipModes.shop)" @click="switchToShop">{{ loc.eq_shop }}</i></button>
  3193. </div>
  3194.  
  3195. <div id="equip_purchase_top" class="equip_purchase_top">
  3196. <!-- <div></div> -->
  3197. <price-tag id="price_tag" class="ss_marginright" v-if="equip.buyingItem" ref="price_tag" :loc="loc" :item="equip.buyingItem" @buy-item-clicked="onBuyItemClicked"></price-tag>
  3198. <physical-tag id="physical-tag" class="ss_marginright" v-if="equip.physicalUnlockPopup.item" ref="physical-tag" :loc="loc" :item="equip.physicalUnlockPopup.item" @buy-item-clicked="onBuyItemClicked"></physical-tag>
  3199. <!-- <p v-if="equip.buyingItem">{{ equip.buyingItem }}</p>
  3200. <p v-if="equip.physicalUnlockPopup">{{ equip.physicalUnlockPopup.item }}</p> -->
  3201.  
  3202. <!--<item-timer id="item_timer" ref="item_timer" :loc="loc"></item-timer>-->
  3203. </div>
  3204.  
  3205. <div id="equip_weapon_panel">
  3206. <weapon-select-panel id="weapon_select" :current-class="classIdx" @changed-class="onChangedClass"></weapon-select-panel>
  3207. <button class="ss_button btn_md btn_red bevel_red" @click="onBackClick"><i class="fas fa-backward"></i> {{ loc.back }}</button>
  3208. </div>
  3209. </section>
  3210. <!-- end .middle_panel -->
  3211.  
  3212. <section id="equip_panel_right" class="equip_panel right_panel">
  3213. <item-type-selector id="item_type_selector" ref="item_type_selector" :selected-item-type="equip.selectedItemType" :show-special-items="equip.showSpecialItems" :in-shop="isInShop" @item-type-changed="onItemTypeChanged" @tagged-items-clicked="onTaggedItemsClicked"></item-type-selector>
  3214.  
  3215. <div id="equip_sidebox" class="roundme_md">
  3216. <item-grid id="item_grid" ref="item_grid" :loc="loc" :grid-class="getGridClass" :items="equip.showingItems" :selectedItem="equip.selectedItem" :category-loc-key="equip.categoryLocKey" :in-shop="isInShop" @item-selected="onItemSelected" @switch-to-shop="onSwitchToShopClicked"></item-grid>
  3217. <!--<house-ad-small id="banner-ad" v-show="!isInShop"></house-ad-small>-->
  3218. </div>
  3219. </section>
  3220. <!-- .right_panel-->
  3221.  
  3222. </div>
  3223. </div>
  3224.  
  3225. <!-- Popup: Buy Item -->
  3226. <small-popup id="buyItemPopup" ref="buyItemPopup" @popup-confirm="onBuyItemConfirm">
  3227. <template slot="header">{{ loc.p_buy_item_title }}</template>
  3228. <template slot="content">
  3229. <div>
  3230. <canvas id="buyItemCanvas" ref="buyItemCanvas" width="250" height="250"></canvas>
  3231. </div>
  3232. <div class="f_row f_center">
  3233. <img src="img/ico_goldenEgg.png" class="egg_icon"/>
  3234. <h1>{{ (equip.buyingItem) ? equip.buyingItem.price : '' }}</h1>
  3235. </div>
  3236. </template>
  3237. <template slot="cancel">{{ loc.p_buy_item_cancel }}</template>
  3238. <template slot="confirm">{{ loc.p_buy_item_confirm }}</template>
  3239. </small-popup>
  3240.  
  3241. <!-- Popup: Redeem Code -->
  3242. <small-popup id="redeemCodePopup" ref="redeemCodePopup" :popup-model="equip.redeemCodePopup" @popup-confirm="onRedeemCodeConfirm">
  3243. <template slot="header">{{ loc.p_redeem_code_title }}</template>
  3244. <template slot="content">
  3245. <div class="error_text shadow_red" v-show="equip.redeemCodePopup.showInvalidCodeMsg">{{ loc.p_redeem_code_no_code }}</div>
  3246. <p><input type="text" class="ss_field ss_margintop ss_marginbottom center_cont width_lg" v-model="equip.redeemCodePopup.code" v-bind:placeholder="loc.p_redeem_code_enter"></p>
  3247. </template>
  3248. <template slot="cancel">{{ loc.cancel }}</template>
  3249. <template slot="confirm">{{ loc.confirm }}</template>
  3250. </small-popup>
  3251.  
  3252. <!-- Popup: Physical Unlock -->
  3253. <small-popup id="physicalUnlockPopup" ref="physicalUnlockPopup" :popup-model="equip.physicalUnlockPopup" @popup-confirm="onPhysicalUnlockConfirm">
  3254. <template slot="header">{{ loc.p_physical_unlock_title }}</template>
  3255. <template slot="content">
  3256. <div v-if="(equip.physicalUnlockPopup.item !== null)">
  3257. <div>
  3258. <item :item="equip.physicalUnlockPopup.item" :isSelected="false" :show-item-only="true"></item>
  3259. <div class="f_row f_center">
  3260. <img src="img/ico_goldenEgg.png" class="egg_icon"/>
  3261. <h1>{{ loc.p_buy_special_price }}</h1>
  3262. </div>
  3263. </div>
  3264. <div class="popup_sm__item_desc">
  3265. {{ loc[equip.physicalUnlockPopup.item.item_data.physicalUnlockLocKey] }}
  3266. </div>
  3267. </div>
  3268. </template>
  3269. <template slot="cancel">{{ loc.cancel }}</template>
  3270. <template slot="confirm">{{ loc.confirm }}</template>
  3271. </small-popup>
  3272.  
  3273. </div>
  3274. </script>
  3275.  
  3276. <script id="equipped-slots-template" type="text/x-template">
  3277. <div>
  3278. <h3 class="margins_sm">{{ loc.eq_equipped }}</h3>
  3279. <div id="equip_equippedslots">
  3280. <div class="equip_item roundme_lg clickme f_row f_center" @click="onClick(itemType.Primary)">
  3281. <item id="primary_item" ref="primary_item" v-if="primaryItem" :item="primaryItem" class="equip_icon"></item>
  3282. </div>
  3283.  
  3284. <div class="equip_item roundme_lg clickme f_row f_center" @click="onClick(itemType.Secondary)">
  3285. <item id="secondary_item" ref="secondary_item" v-if="primaryItem" :item="secondaryItem" class="equip_icon"></item>
  3286. </div>
  3287.  
  3288. <div class="equip_item roundme_lg clickme f_row f_center" @click="onClick(itemType.Hat)">
  3289. <item id="hat_item" ref="hat_item" v-if="hatItem" :item="hatItem"></item>
  3290. <div v-if="!hatItem" class="equip_icon equip_icon_hat"></div>
  3291. </div>
  3292.  
  3293. <div class="equip_item roundme_lg clickme f_row f_center" @click="onClick(itemType.Stamp)">
  3294. <item id="stamp_item" ref="stamp_item" v-if="stampItem" :item="stampItem"></item>
  3295. <div v-if="!stampItem" class="equip_icon equip_icon_stamp"></div>
  3296. </div>
  3297. </div>
  3298. </div>
  3299. </script>
  3300.  
  3301. <script>
  3302. var comp_equipped_slots = {
  3303. template: '#equipped-slots-template',
  3304. components: { 'item': comp_item },
  3305. props: ['loc', 'primaryItem', 'secondaryItem', 'hatItem', 'stampItem'],
  3306.  
  3307. data: function () {
  3308. return {
  3309. itemType: ItemType
  3310. }
  3311. },
  3312.  
  3313. methods: {
  3314. onClick: function (itemType) {
  3315. this.$emit('equipped-type-selected', itemType);
  3316. }
  3317. },
  3318.  
  3319. computed: {
  3320. emptyHatClass: function () {
  3321. return (this.hatItem === null) ? 'equip_icon_hat' : '';
  3322. },
  3323.  
  3324. emptyStampClass: function () {
  3325. return (this.stampItem === null) ? 'equip_icon_stamp' : '';
  3326. }
  3327. }
  3328. };
  3329. </script><script id="color-select-template" type="text/x-template">
  3330. <div>
  3331. <h3 class="margins_sm">{{ loc.eq_color }}</h3>
  3332. <div id="equip_free_colors" class="center_cont">
  3333. <svg v-for="(c, index) in freeColors" class="eggIcon equip_color" :style="{ color: c }" :class="isSelectedClass(index)" @click="onClick(index)"><use xlink:href="#icon-egg"></use></svg>
  3334. </div>
  3335. <div id="equip_paid_colors" class="center_cont ss_marginbottom_lg">
  3336. <svg v-for="(c, index) in paidColors" class="eggIcon equip_color" :style="{ color: c }" :class="isSelectedClass(index + freeColors.length)" @click="onClick(index + freeColors.length)"><use :xlink:href="getExtraColorEggIcon(index + freeColors.length)"></use></svg>
  3337. </div>
  3338. </div>
  3339. </script>
  3340.  
  3341. <script>
  3342. var comp_color_select = {
  3343. template: '#color-select-template',
  3344. props: ['loc', 'colorIdx', 'extraColorsLocked'],
  3345.  
  3346. data: function () {
  3347. return {
  3348. freeColors: freeColors,
  3349. paidColors: paidColors
  3350. }
  3351. },
  3352.  
  3353. methods: {
  3354. isSelectedClass: function (idx) {
  3355. return (idx === this.colorIdx) ? 'selected' : ''
  3356. },
  3357.  
  3358. getExtraColorEggIcon: function (idx) {
  3359. return (this.extraColorsLocked === true) ? '#icon-egg-locked' : '#icon-egg';
  3360. },
  3361.  
  3362. onClick: function (idx) {
  3363. if (idx >= freeColors.length && this.extraColorsLocked === true) {
  3364. vueApp.showGoldChickenPopup();
  3365. vueApp.playSound('./sound/ui/ui_chicken.mp3');
  3366. return;
  3367. }
  3368.  
  3369. this.$emit('color-changed', idx);
  3370. }
  3371. }
  3372. };
  3373. </script><script id="item-timer-template" type="text/x-template">
  3374. <div>
  3375. <div id="equip_timerem" class="box_blue3 roundme_sm shadow_blue4">
  3376. <i class="fas fa-hourglass-start"></i> 9{{ loc.eq_day }}<span class="blink">:</span>12{{ loc.eq_hour }}
  3377. <br>{{ loc.eq_remaining }}
  3378. </div>
  3379. </div>
  3380. </script>
  3381.  
  3382. <script>
  3383. var comp_item_timer = {
  3384. template: '#item-timer-template',
  3385. props: ['loc']
  3386. };
  3387. </script><script id="price-tag-template" type="text/x-template">
  3388. <div id="equip_purchase_items" class="equip_purchase_items">
  3389. <div id="equip_pricetag" class="equip_pricetag shadow_blue2">
  3390. <img src="img/pricetag_left.png" class="equip_pricetag__endpiece">
  3391. <div class="equip_pricetag__tag equip_pricetag__is_buy_tag">
  3392. <img src="img/ico_goldenEgg.png">{{ item.price }}
  3393. </div>
  3394. <img src="img/pricetag_right.png" class="equip_pricetag__endpiece">
  3395. </div>
  3396. <button class="ss_button btn_yolk bevel_yolk is_purchase_btn" @click="onBuyClick">{{ loc.eq_buy }}</button>
  3397. </div>
  3398. </script>
  3399.  
  3400. <script>
  3401. var comp_price_tag = {
  3402. template: '#price-tag-template',
  3403. props: ['loc', 'item'],
  3404.  
  3405. methods: {
  3406. onBuyClick: function () {
  3407. this.$emit('buy-item-clicked', this.item);
  3408. }
  3409. }
  3410. };
  3411. </script><script id="physical-tag-template" type="text/x-template">
  3412. <div id="equip_get_physical_item" class="equip_purchase_items">
  3413. <div id="equip_pricetag" class="equip_pricetag shadow_blue2">
  3414. <img src="img/pricetag_left.png">
  3415. <div class="equip_pricetag__tag equip_pricetag__is_special_tag">
  3416. <img src="img/ico_goldenEgg.png" class="ss_marginright">{{ loc.p_buy_special_price }}
  3417. </div>
  3418. <img src="img/pricetag_right.png">
  3419. </div>
  3420. <button class="ss_button btn_yolk bevel_yolk is_special_get_btn" @click="onBuyClick">{{ loc.p_chicken_goldbutton }}</button>
  3421. </div>
  3422. </script>
  3423.  
  3424. <script>
  3425. var comp_physical_tag = {
  3426. template: '#physical-tag-template',
  3427. props: ['loc', 'item'],
  3428.  
  3429. methods: {
  3430. onBuyClick: function () {
  3431. this.$emit('buy-item-clicked', this.item);
  3432. }
  3433. }
  3434. };
  3435. </script><script id="item-type-selector-template" type="text/x-template">
  3436. <div>
  3437. <div id="equip_itemtype" class="equip_panelhead">
  3438. <img src="img/ico_weaponPrimary.png" class="ico_itemtype clickme roundme_lg" :class="getSelectedClass(itemType.Primary)" @click="onItemTypeClick(itemType.Primary)">
  3439. <img src="img/ico_weaponSecondary.png" class="ico_itemtype clickme roundme_lg" :class="getSelectedClass(itemType.Secondary)" @click="onItemTypeClick(itemType.Secondary)">
  3440. <img src="img/ico_hat.png" class="ico_itemtype clickme roundme_lg" :class="getSelectedClass(itemType.Hat)" @click="onItemTypeClick(itemType.Hat)">
  3441. <img src="img/ico_stamp.png" class="ico_itemtype clickme roundme_lg" :class="getSelectedClass(itemType.Stamp)" @click="onItemTypeClick(itemType.Stamp)">
  3442. <img src="img/ico_specialItem.png" v-show="inShop && showSpecialItems" class="ico_itemtype clickme roundme_lg" :class="getSelectedClass('tagged')" @click="onTaggedTypeClick">
  3443. </div>
  3444. </div>
  3445. </script>
  3446.  
  3447. <script>
  3448. var comp_item_type_selector = {
  3449. template: '#item-type-selector-template',
  3450. props: ['showSpecialItems', 'selectedItemType', 'inShop'],
  3451.  
  3452. data: function () {
  3453. return {
  3454. itemType: ItemType,
  3455. showingTagged: false
  3456. }
  3457. },
  3458.  
  3459. methods: {
  3460. onItemTypeClick: function (itemType) {
  3461. this.$emit('item-type-changed', itemType);
  3462. },
  3463.  
  3464. onTaggedTypeClick: function () {
  3465. this.$emit('tagged-items-clicked');
  3466. },
  3467.  
  3468. getSelectedClass: function (itemType) {
  3469. return (itemType === this.selectedItemType)
  3470. ? 'selected'
  3471. : '';
  3472. }
  3473. }
  3474. };
  3475. </script><script id="item-grid-template" type="text/x-template">
  3476. <div>
  3477. <div id="item_mask"></div>
  3478. <h3 class="margins_sm">{{ loc[categoryLocKey] }}</h3>
  3479. <div id="equip_grid" :class="gridClass">
  3480. <item v-for="i in items" :loc="loc" :item="i" :key="i.id" :isSelected="isSelected(i)" @item-selected="onItemSelected"></item>
  3481. <div v-show="!inShop" class="store_item roundme_lg '.$is_hi.' '.$is_na.' clickme morestuff bevel_green" @click="onSwitchToShopClick"></div>
  3482. <div v-show="inShop && (items.length === 0)" class="store_item roundme_lg '.$is_hi.' '.$is_na.' soldout">
  3483. <div class="soldout_head shadow_bluebig5" v-html="loc.eq_sold_out_head"></div>
  3484. <div class="soldout_text" v-html="loc.eq_sold_out_text"></div>
  3485. </div>
  3486. </div>
  3487. </div>
  3488. </script>
  3489.  
  3490. <script>
  3491. var comp_item_grid = {
  3492. template: '#item-grid-template',
  3493. components: { 'item': comp_item },
  3494. props: ['loc', 'items', 'selectedItem', 'gridClass', 'categoryLocKey', 'inShop'],
  3495.  
  3496. methods: {
  3497. onItemSelected: function (selectedItem) {
  3498. this.$emit('item-selected', selectedItem);
  3499. },
  3500.  
  3501. isSelected: function (item) {
  3502. if (!hasValue(this.selectedItem)) {
  3503. return false;
  3504. }
  3505.  
  3506. return (this.selectedItem.id === item.id);
  3507. },
  3508.  
  3509. onSwitchToShopClick: function () {
  3510. this.$emit('switch-to-shop');
  3511. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  3512. }
  3513. },
  3514.  
  3515. computed: {
  3516. categoryName: function () {
  3517. if (!hasValue(this.selectedItem)) {
  3518. return null;
  3519. }
  3520.  
  3521. return this.loc['item_type_' + this.selectedItem.item_type_id];
  3522. }
  3523. }
  3524. };
  3525. </script>
  3526. <script>
  3527. var comp_equip_screen = {
  3528. template: '#equip-screen-template',
  3529. components: {
  3530. 'account-panel': comp_account_panel,
  3531. 'equipped-slots': comp_equipped_slots,
  3532. 'color-select': comp_color_select,
  3533. 'item-timer': comp_item_timer,
  3534. 'price-tag': comp_price_tag,
  3535. 'physical-tag': comp_physical_tag,
  3536. 'item-type-selector': comp_item_type_selector,
  3537. 'item-grid': comp_item_grid,
  3538. 'house-ad-small': comp_house_ad_small,
  3539. 'weapon-select-panel': comp_weapon_select_panel,
  3540. 'item': comp_item,
  3541. // 'account-panel': comp_account_panel,
  3542. 'house-ad-small': comp_house_ad_small
  3543. },
  3544.  
  3545. data: function () {
  3546. return vueData;
  3547. },
  3548.  
  3549. equippedItems: {},
  3550.  
  3551. methods: {
  3552. setup: function (itemType) {
  3553. if (!itemType) { itemType = ItemType.Primary; }
  3554. this.updateEquippedItems();
  3555. this.poseEquippedItems();
  3556. if (itemType === 'tagged') {
  3557. this.populateItemGridWithTagged(this.equip.specialItemsTag);
  3558. } else {
  3559. this.populateItemGridWithType(itemType);
  3560. }
  3561. this.selectEquippedItemForType();
  3562. },
  3563.  
  3564. updateEquippedItems: function () {
  3565. this.$options.equippedItems = extern.getEquippedItems();
  3566.  
  3567. this.equip.equippedHat = this.$options.equippedItems[ItemType.Hat];
  3568. this.equip.equippedStamp = this.$options.equippedItems[ItemType.Stamp];
  3569. this.equip.equippedPrimary = this.$options.equippedItems[ItemType.Primary];
  3570. this.equip.equippedSecondary = this.$options.equippedItems[ItemType.Secondary];
  3571. },
  3572.  
  3573. poseEquippedItems: function () {
  3574. this.posingHat = this.equip.equippedHat;
  3575. this.posingStamp = this.equip.equippedStamp;
  3576. this.posingWeapon = (this.equip.showingWeaponType === ItemType.Primary)
  3577. ? this.equip.equippedPrimary
  3578. : this.equip.equippedSecondary;
  3579.  
  3580. this.workItBaby();
  3581. },
  3582.  
  3583. selectEquippedItemForType: function () {
  3584. switch (this.equip.selectedItemType) {
  3585. case ItemType.Hat: this.equip.selectedItem = this.equip.equippedHat; break;
  3586. case ItemType.Stamp: this.equip.selectedItem = this.equip.equippedStamp; break;
  3587. case ItemType.Primary: this.equip.selectedItem = this.equip.equippedPrimary; break;
  3588. case ItemType.Secondary: this.equip.selectedItem = this.equip.equippedSecondary; break;
  3589. }
  3590. },
  3591.  
  3592. populateItemGridWithType: function (itemType) {
  3593. this.equip.selectedItemType = itemType;
  3594. var items = extern.getItemsOfType(itemType);
  3595. this.populateItemGrid(items);
  3596.  
  3597. this.equip.categoryLocKey = 'item_type_{0}{1}'.format(itemType, ((itemType === ItemType.Primary) ? '_' + this.classIdx : ''));
  3598. },
  3599.  
  3600. populateItemGridWithTagged: function (tag) {
  3601. var items = extern.getTaggedItems(tag);
  3602. this.populateItemGrid(items);
  3603. this.equip.categoryLocKey = 'item_type_5';
  3604. },
  3605.  
  3606. populateItemGrid: function (items) {
  3607. if (this.equip.mode === vueData.equip.equipModes.inventory) {
  3608. items = items.filter(i => {
  3609. return extern.isItemOwned(i) || (i.is_available && i.unlock === "default");
  3610. });
  3611. } else {
  3612. items = items.filter(i => {
  3613. return i.is_available && !extern.isItemOwned(i) && i.unlock !== "default";
  3614. })
  3615. }
  3616.  
  3617. this.equip.showingItems = items;
  3618. },
  3619.  
  3620. workItBaby: function () {
  3621. extern.poseWithItem(ItemType.Hat, this.posingHat);
  3622. extern.poseWithItem(ItemType.Stamp, this.posingStamp);
  3623. extern.poseWithItem(this.posingWeapon.item_type_id, this.posingWeapon);
  3624. },
  3625.  
  3626. onBackClick: function () {
  3627. extern.saveEquipment();
  3628.  
  3629. this.equip.showingWeaponType = ItemType.Primary;
  3630. this.poseEquippedItems();
  3631.  
  3632. if (!extern.inGame) {
  3633. vueApp.switchToHomeUi();
  3634. } else {
  3635. extern.closeEquipInGame();
  3636. vueApp.switchToGameUi();
  3637. }
  3638.  
  3639. vueApp.playSound('./sound/ui/ui_popupclose.mp3');
  3640. },
  3641.  
  3642. onItemTypeChanged: function (itemType) {
  3643. this.switchItemType(itemType);
  3644. },
  3645.  
  3646. switchItemType: function (itemType) {
  3647. if (itemType !== this.equip.selectedItemType) {
  3648. if (itemType === ItemType.Primary || itemType === ItemType.Secondary) {
  3649. this.equip.showingWeaponType = itemType;
  3650. }
  3651. this.poseEquippedItems();
  3652. this.populateItemGridWithType(itemType);
  3653. if (this.equip.mode === this.equip.equipModes.inventory) {
  3654. this.selectEquippedItemForType();
  3655. } else {
  3656. this.selectFirstItemInShop();
  3657. }
  3658. }
  3659. if (!this.isInShop) {
  3660. this.hideItemForSale();
  3661. this.hideItemForSpecial();
  3662. }
  3663. vueApp.playSound('./sound/ui/ui_click.mp3');
  3664. },
  3665.  
  3666. onTaggedItemsClicked: function () {
  3667. this.showTaggedItems(this.equip.specialItemsTag);
  3668. this.selectFirstItemInShop();
  3669. vueApp.playSound('./sound/ui/ui_click.mp3');
  3670. },
  3671.  
  3672. showTaggedItems: function (tag) {
  3673. this.equip.selectedItemType = 'tagged';
  3674.  
  3675. if (this.equip.mode === this.equip.equipModes.inventory && !this.ownsTaggedItems(this.equip.specialItemsTag)) {
  3676. this.equip.mode = this.equip.equipModes.shop;
  3677. }
  3678.  
  3679. this.populateItemGridWithTagged(tag);
  3680. },
  3681.  
  3682. switchToInventory: function () {
  3683. if (this.equip.selectedItemType === 'tagged' && this.equip.mode === this.equip.equipModes.shop) {
  3684. if (!this.ownsTaggedItems(this.equip.specialItemsTag)) {
  3685. this.switchItemType(ItemType.Primary);
  3686. }
  3687. }
  3688.  
  3689. this.equip.mode = this.equip.equipModes.inventory;
  3690. this.hideItemForSale();
  3691. this.hideItemForSpecial();
  3692. this.poseEquippedItems();
  3693. this.showItemsAfterEquipModeSwitch();
  3694. this.selectEquippedItemForType();
  3695. vueApp.playSound('./sound/ui/ui_toggletab.mp3');
  3696. },
  3697.  
  3698. ownsTaggedItems: function (tag) {
  3699. return extern.getTaggedItems(tag).filter(i => {
  3700. return extern.isItemOwned(i);
  3701. }).length > 0;
  3702. },
  3703.  
  3704. selectFirstItemInShop: function () {
  3705. if (this.isInShop && this.equip.showingItems.length > 0) {
  3706. this.selectItem(this.equip.showingItems[0]);
  3707. }
  3708. },
  3709.  
  3710. switchToShop: function () {
  3711. this.equip.mode = this.equip.equipModes.shop;
  3712. this.showItemsAfterEquipModeSwitch();
  3713. this.selectFirstItemInShop();
  3714. vueApp.conditionalAnonWarningCall();
  3715. vueApp.playSound('./sound/ui/ui_toggletab.mp3');
  3716. },
  3717.  
  3718. showItemsAfterEquipModeSwitch: function () {
  3719. if (this.equip.selectedItemType !== 'tagged') {
  3720. this.populateItemGridWithType(this.equip.selectedItemType);
  3721. } else {
  3722. this.showTaggedItems(this.equip.specialItemsTag)
  3723. }
  3724. },
  3725.  
  3726. onEquippedTypeSelected: function (itemType) {
  3727. this.equip.selectedItemType = itemType;
  3728. if (this.equip.selectedItemType === ItemType.Primary || this.equip.selectedItemType === ItemType.Secondary) {
  3729. this.equip.showingWeaponType = itemType;
  3730. }
  3731. this.switchToInventory();
  3732. },
  3733.  
  3734. onChangedClass: function () {
  3735. this.hideItemForSale();
  3736. this.hideItemForSpecial();
  3737.  
  3738. this.updateEquippedItems();
  3739. this.poseEquippedItems();
  3740. this.populateItemGridWithType(this.equip.selectedItemType);
  3741. },
  3742.  
  3743. autoSelectItem: function (item) {
  3744. if (extern.isItemOwned(item)) {
  3745. this.switchToInventory();
  3746. } else {
  3747. this.switchToShop();
  3748. }
  3749. this.switchItemType(item.item_type_id);
  3750. this.selectItem(item);
  3751. },
  3752.  
  3753. onItemSelected: function (item) {
  3754. this.selectItem(item);
  3755. },
  3756.  
  3757. selectItem: function (item) {
  3758. var selectingSame = hasValue(this.equip.selectedItem) && this.equip.selectedItem.id === item.id;
  3759. var selectedId = selectingSame ? this.equip.selectedItem.id : null;
  3760. var isWeapon = (item.item_type_id === ItemType.Primary || item.item_type_id === ItemType.Secondary);
  3761. vueApp.playSound('./sound/ui/ui_click.mp3');
  3762.  
  3763. if (selectingSame) {
  3764. if (this.isInShop) {
  3765. // Revert to equipped weapon
  3766. item = this.$options[this.equip.selectedItem.item_type_id];
  3767. } else {
  3768. // Take off hat or stamp
  3769. if (!isWeapon) {
  3770. item = null;
  3771. extern.removeItemType(this.equip.selectedItem.item_type_id);
  3772. }
  3773. }
  3774. }
  3775.  
  3776. // Take off any items being tried on
  3777. this.poseEquippedItems();
  3778.  
  3779. this.equip.selectedItem = item;
  3780. extern.tryEquipItem(item);
  3781. this.updateEquippedItems();
  3782.  
  3783. if (hasValue(item)) {
  3784. this.poseWithItem(item);
  3785.  
  3786. if (this.isInShop) {
  3787. switch (item.unlock) {
  3788. case "physical":
  3789. console.log('purchasing physical item');
  3790.  
  3791. if ( !selectingSame ) {
  3792. this.offerItemForSpecial(item)
  3793. this.hideItemForSale();
  3794. } else {
  3795. this.hideItemForSpecial();
  3796. }
  3797. // this.$refs.physicalUnlockPopup.toggle();
  3798. break;
  3799. case "purchase":
  3800. if (!selectingSame) {
  3801. this.offerItemForSale(item);
  3802. this.hideItemForSpecial();
  3803. } else {
  3804. this.hideItemForSale();
  3805. }
  3806. break;
  3807. }
  3808. }
  3809. } else {
  3810. this.poseEquippedItems();
  3811. this.hideItemForSale();
  3812. this.hideItemForSpecial();
  3813.  
  3814. }
  3815. },
  3816.  
  3817. poseWithItem: function (item) {
  3818. switch (item.item_type_id) {
  3819. case ItemType.Hat: this.posingHat = item; break;
  3820. case ItemType.Stamp: this.posingStamp = item; break;
  3821. case ItemType.Primary:
  3822. case ItemType.Secondary: this.posingWeapon = item; break;
  3823. }
  3824.  
  3825. this.workItBaby();
  3826. },
  3827.  
  3828. getButtonToggleClass: function (equipMode) {
  3829. return (equipMode === this.equip.mode) ? 'btn_toggleon' : 'btn_toggleoff';
  3830. },
  3831.  
  3832. offerItemForSpecial: function(item) {
  3833. return this.equip.physicalUnlockPopup.item = item;
  3834. },
  3835.  
  3836. hideItemForSpecial: function() {
  3837. this.equip.physicalUnlockPopup.item = null;
  3838. },
  3839.  
  3840. offerItemForSale: function (item) {
  3841. this.equip.buyingItem = item;
  3842. },
  3843.  
  3844. hideItemForSale: function () {
  3845. this.equip.buyingItem = null;
  3846. // this.equip.physicalUnlockPopup.item = null
  3847. },
  3848.  
  3849. onBuyItemClicked: function () {
  3850. // If item is buying item show buyItemPopup or show physicalUnlockPopup
  3851. this.equip.buyingItem ? this.$refs.buyItemPopup.toggle() : this.$refs.physicalUnlockPopup.toggle();
  3852. this.equip.buyingItem ? extern.renderItemToCanvas(this.equip.buyingItem, this.$refs.buyItemCanvas) : null;
  3853. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  3854. },
  3855.  
  3856. onBuyItemConfirm: function () {
  3857. extern.api_buy(this.equip.buyingItem, this.boughtItemSuccess, this.boughtItemFailed);
  3858. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  3859. },
  3860.  
  3861. boughtItemSuccess: function () {
  3862. this.equip.selectedItem = this.equip.buyingItem;
  3863. var itemType = this.equip.selectedItem.item_type_id;
  3864. if (itemType === ItemType.Primary || itemType === ItemType.Secondary) {
  3865. this.equip.showingWeaponType = itemType;
  3866. }
  3867. this.hideItemForSale();
  3868. this.setup(this.equip.selectedItemType);
  3869. this.updateEquippedItems();
  3870. this.poseEquippedItems();
  3871. this.selectEquippedItemForType();
  3872. },
  3873.  
  3874. boughtItemFailed: function () {
  3875. vueApp.showGenericPopup('p_buy_error_title', 'p_buy_error_content', 'ok');
  3876. vueApp.playSound('./sound/ui/ui_reset.mp3');
  3877. },
  3878.  
  3879. onRedeemClick: function () {
  3880. this.$refs.redeemCodePopup.code = '';
  3881. this.$refs.redeemCodePopup.toggle();
  3882. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  3883. },
  3884.  
  3885. onRedeemCodeConfirm: function () {
  3886. extern.api_redeem(this.equip.redeemCodePopup.code, this.redeemCodeSuccess, this.redeemCodeFailed);
  3887. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  3888. },
  3889.  
  3890. redeemCodeSuccess: function (eggs, items) {
  3891. this.populateItemGridWithType(this.equip.selectedItemType);
  3892.  
  3893. this.giveStuffPopup.eggs = eggs;
  3894. this.giveStuffPopup.items = items;
  3895. this.$refs.giveStuffPopup.toggle();
  3896. },
  3897.  
  3898. redeemCodeFailed: function () {
  3899. vueApp.showGenericPopup('p_redeem_error_title', 'p_redeem_error_content', 'ok');
  3900. vueApp.playSound('./sound/ui/ui_reset.mp3');
  3901. },
  3902.  
  3903. onPhysicalUnlockConfirm: function () {
  3904. window.open(this.equip.physicalUnlockPopup.item.item_data.physicalItemStoreURL, '_blank');
  3905. },
  3906.  
  3907. onColorChanged: function (colorIdx) {
  3908. this.equip.colorIdx = colorIdx;
  3909. extern.setShellColor(this.equip.colorIdx);
  3910. vueApp.playSound('./sound/ui/ui_onchange.mp3');
  3911. },
  3912.  
  3913. onSwitchToShopClicked: function () {
  3914. this.switchToShop();
  3915. }
  3916. },
  3917.  
  3918. computed: {
  3919. isInShop: function () {
  3920. return (this.equip.mode === this.equip.equipModes.shop);
  3921. },
  3922.  
  3923. getGridClass: function () {
  3924. return this.isInShop ? '' : 'equip_grid_short';
  3925. }
  3926. }
  3927. };
  3928. </script><script id="game-screen-template" type="text/x-template">
  3929. <div>
  3930. <account-panel id="game_account_panel" ref="accountPanel" :loc="loc" :eggs="eggs" :show-bottom="false" :show-corner-buttons="ui.showCornerButtons" :ui="ui"></account-panel>
  3931.  
  3932. <div id="chickenBadge" ref="chickenBadge" style="display: none;"><img src="img/ico_chickenBadge.png"></div>
  3933.  
  3934. <!-- Reticle -->
  3935. <div id="reticleContainer">
  3936. <div id="crosshairContainer">
  3937. <div id="crosshair0" class="crosshair"></div>
  3938. <div id="crosshair1" class="crosshair"></div>
  3939. <div id="crosshair2" class="crosshair"></div>
  3940. <div id="crosshair3" class="crosshair"></div>
  3941. </div>
  3942.  
  3943. <div id="shotReticleContainer">
  3944. <div class="shotReticle black"></div>
  3945. <div class="shotReticle black"></div>
  3946. <div class="shotReticle white"></div>
  3947. <div class="shotReticle white"></div>
  3948. </div>
  3949.  
  3950. <div id="readyBrackets">
  3951. <div class="readyBracket"></div>
  3952. <div class="readyBracket"></div>
  3953. <div class="readyBracket"></div>
  3954. <div class="readyBracket"></div>
  3955. </div>
  3956. </div>
  3957.  
  3958. <!-- Scope -->
  3959. <div id="scopeBorder">
  3960. <div id="maskleft"></div>
  3961. <div id="maskmiddle"></div>
  3962. <div id="maskright"></div>
  3963. </div>
  3964.  
  3965. <!-- Best Streak -->
  3966. <div id="best_streak_container">
  3967. <!--<h3>{{ loc.ui_game_beststreak }}</h3>-->
  3968. <h1 id="bestStreak">x0</h1>
  3969. </div>
  3970.  
  3971. <!-- Team Scores -->
  3972. <div id="teamScores">
  3973. <div id="teamScore2" class="teamScore red inactive">
  3974. <div id="teamScoreNum2" class="number">0</div>
  3975. <div class="teamLetter red" style="color: #f00;">R</div>
  3976. </div>
  3977. <div id="teamScore1" class="teamScore blue inactive">
  3978. <div id="teamScoreNum1" class="number">0</div>
  3979. <div class="teamLetter blue" style="color: #0af;">B</div>
  3980. </div>
  3981. <!--<div>
  3982. <img src="img/spatulaIcon.png" style="width: 3em; transform: rotate(60deg)">
  3983. </div>-->
  3984. </div>
  3985.  
  3986. <!-- Weapon -->
  3987. <div id="weaponBox">
  3988. <div id="grenades">
  3989. <img id="grenade3" class="grenade" src="img/ico_grenadeEmpty.png?v=1"/>
  3990. <img id="grenade2" class="grenade" src="img/ico_grenadeEmpty.png?v=1"/>
  3991. <img id="grenade1" class="grenade" src="img/ico_grenadeEmpty.png?v=1"/>
  3992. </div>
  3993. <h2 id="weaponName"></h2>
  3994. <h2 id="ammo" class="shadow_grey"></h2>
  3995. </div>
  3996.  
  3997. <!-- Health -->
  3998. <div id="health">
  3999. <svg class="healthSvg">
  4000. <circle id="healthBar" class="healthBar" cx="50%" cy="50%" r="2.15em" />
  4001. <circle class="healthYolk" cx="50%" cy="50%" r="1.35em" />
  4002. </svg>
  4003.  
  4004. <div id="healthHp">100</div>
  4005. </div>
  4006.  
  4007. <!-- Spatula -->
  4008. <img id="spatulaPlayer" src="img/spatulaIcon.png" />
  4009.  
  4010. <!-- Grenade throw power -->
  4011. <div id="grenadeThrowContainer">
  4012. <div id="grenadeThrow"></div>
  4013. </div>
  4014.  
  4015. <!-- Kill -->
  4016. <div id="killBox" class="shadow_grey">
  4017. <h3>{{ loc.ui_game_youkilled }}</h3>
  4018. <h2 id="KILLED_NAME"></h2>
  4019. <h3 id="KILL_STREAK"></h3>
  4020. </div>
  4021.  
  4022. <!-- Death -->
  4023. <div id="deathBox">
  4024. <h3>{{ loc.ui_game_killedby }}</h3>
  4025. <h2 id="KILLED_BY_NAME"></h2>
  4026. <h3 id="respawnMessage"></h3>
  4027. </div>
  4028.  
  4029. <!-- Game messages -->
  4030. <div id="gameMessage"></div>
  4031.  
  4032. <!-- Chat -->
  4033. <div id="chatOut" class="chat roundme_sm"></div>
  4034.  
  4035. <input id="chatIn" class="chat roundme_sm" maxlength=64 tabindex=-1 placeholder="Press TAB to exit" onkeydown="extern.onChatKeyDown(event)"></input>
  4036.  
  4037. <!-- Kill ticker -->
  4038. <div id="killTicker" class="chat"></div>
  4039.  
  4040. <!-- Spectator controls -->
  4041. <div id="spectate">
  4042. {{ loc.ui_game_spectating }}
  4043. </div>
  4044.  
  4045. <div id="serverAndMapInfo" class="shadow_grey"></div>
  4046.  
  4047. <!-- Ingame UI Stuff -->
  4048. <div id="inGameUI">
  4049. <div id="readouts" class="shadow_grey">
  4050. {{ loc.ui_game_fps }}: <div id="FPS"></div><br>
  4051. {{ loc.ui_game_ping }}: <div id="ping"></div>
  4052. </div>
  4053.  
  4054. <!-- Corner icon buttons -->
  4055. <!--
  4056. <div id="corner" style="float: right; margin-top: 0.5em;">
  4057. <div id="currentBalanceContainer" style="display: none; position: relative; left: -1em; top: 0.15em;">
  4058. <span id="currentBalance" style="display: inline-block; font-size: 1.7em; position: relative; top: -0.25em; left: -0.1em; color: white;"></span>
  4059. boopdiddyboop<img src="img/egg_icon.png" style="width: 1.6em; height: 2em;" />
  4060. </div>
  4061. <div id="cornerButtons" style="display: none; margin-bottom: 0.5em; text-align: right; float: right;">
  4062. <-<img id="homeButton" style="display: none; margin-right: 0.5em;" title="Home" class="icon" src="img/home.png?v=1" onclick="extern.showMainMenuConfirm()" />
  4063. <img id="friendsButton" style="display: none; margin-right: 0.5em;" title="Invite friends" class="icon" src="img/friends.png?v=1" onclick="extern.inviteFriends()" />
  4064. <img style="margin-right: 0.5em;" title="Feedback" class="icon" src="img/feedback.png?v=1" onclick="extern.showFeedbackForm()" />
  4065. <img style="margin-right: 0.5em;" title="Settings" class="icon" src="img/settings.png?v=1" onclick="extern.openSettingsMenu()" />
  4066. <img class="icon" title="Toggle fullscreen" src="img/fullScreen.png?v=1" onclick="extern.toggleFullscreen()" /> ->
  4067. </div>
  4068. </div>
  4069. -->
  4070. </div>
  4071.  
  4072. <!-- Popup: Mute/Boot Player -->
  4073. <small-popup id="playerActionsPopup" ref="playerActionsPopup" @popup-cancel="onPlayerActionsCancel" @popup-closed="onPlayerActionsCancel" :hide-confirm="true">
  4074. <template slot="header">{{ playerActionsPopup.playerName }}</template>
  4075. <template slot="content">
  4076. <p>{{ loc.ui_game_playeractions_header }}</p>
  4077. <h4 class="ss_button btn_medium btn_blue bevel_blue" v-on:click="onMuteClicked">{{ muteButtonLabel }}</h4>
  4078. <h4 class="ss_button btn_medium btn_yolk bevel_yolk" v-if="playerActionsPopup.isGameOwner" v-on:click="onBootClicked">{{ loc.ui_game_playeractions_boot }}</h4>
  4079. </template>
  4080. <template slot="cancel">{{ loc.cancel }}</template>
  4081. </small-popup>
  4082.  
  4083. <!-- Popup: Switch Team -->
  4084. <small-popup id="switchTeamPopup" ref="switchTeamPopup" @popup-cancel="onSwitchTeamCancel" :overlay-close="false" @popup-closed="onSwitchTeamCancel" @popup-confirm="onSwitchTeamConfirm">
  4085. <template slot="header">{{ loc.p_switch_team_title }}</template>
  4086. <template slot="content">
  4087. <h4 class="roundme_sm" :class="newTeamColorCss">{{ newTeamName }} <i class="fa fa-flag"></i></h4>
  4088. <p>{{ loc.p_switch_team_text }}</p>
  4089. </template>
  4090. <template slot="cancel">{{ loc.no }}</template>
  4091. <template slot="confirm">{{ loc.yes }}</template>
  4092. </small-popup>
  4093.  
  4094. <!-- Popup: Share Link -->
  4095. <small-popup id="shareLinkPopup" ref="shareLinkPopup" :popup-model="game.shareLinkPopup" @popup-confirm="onShareLinkConfirm" @popup-closed="onShareLinkClosed">
  4096. <template slot="header">{{ loc.p_sharelink_title }}</template>
  4097. <template slot="content">
  4098. <p>{{ loc.p_sharelink_text }}</p>
  4099. <p><input ref="shareLinkUrl" type="text" class="ss_field ss_margintop ss_marginbottom fullwidth" v-model="game.shareLinkPopup.url" @focus="$event.target.select()"></p>
  4100. </template>
  4101. <template slot="cancel">{{ loc.close }}</template>
  4102. <template slot="confirm">{{ loc.p_sharelink_copylink }}</template>
  4103. </small-popup>
  4104.  
  4105. <!-- Popup: Leave Game Confirm -->
  4106. <small-popup id="leaveGameConfirmPopup" ref="leaveGameConfirmPopup" :overlay-close="false" :hide-close="true" @popup-confirm="onLeaveGameConfirm" @popup-cancel="onLeaveGameCancel">
  4107. <template slot="header">{{ loc.leave_game_title }}</template>
  4108. <template slot="content">
  4109. <p>{{ loc.leave_game_text }}</p>
  4110. </template>
  4111. <template slot="cancel">{{ loc.no }}</template>
  4112. <template slot="confirm">{{ loc.yes }}</template>
  4113. </small-popup>
  4114.  
  4115. <div id="inGameScaler">
  4116.  
  4117. <div class="player__container">
  4118. <!-- Player List -->
  4119. <div id="playerSlot" class="playerSlot" style="display: none">
  4120. <div style="
  4121. display: table-cell;
  4122. border-radius: 0.2em;
  4123. padding-top: 0.05em; padding-bottom: 0.05em;
  4124. padding-left: 0.5em; padding-right: 0.5em;
  4125. overflow-y: hidden;
  4126. font-weight: bold;
  4127. ">
  4128. <span></span> <!-- Name -->
  4129. <span style="padding-left: 1em"></span> <!-- Score -->
  4130. </div>
  4131. <div style="display: table-cell;"></div> <!-- Icons -->
  4132. </div>
  4133. <div id="playerList"></div>
  4134. </div>
  4135. <!-- end .player__container -->
  4136.  
  4137. <div class="pause-popup--container">
  4138. <!-- Popup: Pause -->
  4139. <large-popup id="pausePopup" ref="pausePopup" hide-close="true" :overlay-close="false" :overlay-class="ui.overlayClass.inGame">
  4140. <template slot="content">
  4141. <div id="pausePopupInnards" class="box_blue2 roundme_sm fullwidth f_row">
  4142.  
  4143. <div id="pauseButtons">
  4144. <button @click="onHomeClicked" class="ss_button btn_blue bevel_blue"><i class="fa fa-home"></i> {{ loc.p_pause_home }}</button>
  4145. <button @click="onEquipClicked()" class="ss_button btn_blue bevel_blue"><i class="fas fa-star"></i> {{ loc.p_pause_equipment }}</button>
  4146. <!-- Don't have leaderboards yet <button class="ss_button btn_blue bevel_blue"><i class="fa fa-trophy"></i> {{ loc.p_pause_leaderboards }}</button> -->
  4147. <!-- <button class="ss_button btn_blue bevel_blue"><i class="fa fa-shopping-cart"></i> {{ loc.p_pause_shop }}</button> -->
  4148. <button @click="onHelpClicked" class="ss_button btn_blue bevel_blue"><i class="fa fa-question"></i> {{ loc.p_pause_help }}</button>
  4149. <button @click="onShareLinkClicked" class="ss_button btn_blue bevel_blue"><i class="fa fa-link"></i> {{ loc.p_pause_sharelink }}</button>
  4150.  
  4151. <button @click="onSettingsClicked" class="ss_button btn_blue bevel_blue"><i class="fa fa-cog"></i> {{ loc.p_pause_settings }}</button>
  4152. </div>
  4153.  
  4154. <div id="popupTipDay" class="popupTipDay roundme_sm">
  4155. <h3><i class="fa fa-lightbulb fa-lg"></i> {{ loc.p_pause_tipoftheday }}</h3>
  4156. <p>{{ (loc.tip_ofthe_day ? loc.tip_ofthe_day[game.tipIdx] : '') }}</p>
  4157. <div id="btn_horizontal" class="pause-popup--btn-group">
  4158. <div class="btn-container">
  4159. <button v-show="isTeamGame" @click="onSwitchTeamClicked" class="ss_button btn__team_switch" :class="teamColorCss">{{ teamName }} <i class="fa fa-flag"></i></button>
  4160. </div>
  4161. <div class="btn-container">
  4162. <button @click="onSpectateClicked()" class="ss_button btn_blue bevel_blue btn_sm" v-show="!isRespawning"><i class="fas fa-eye"></i> {{ loc.p_pause_spectate }}</button>
  4163. <button @click="onPlayClicked()" class="ss_button btn_green bevel_green btn_sm" v-show="!isRespawning"><i class="fa fa-play"></i> {{ loc.p_pause_play }}</button>
  4164. <button class="fullwidth btn__respawning" v-show="isRespawning">{{ game.respawnTime }}</button>
  4165. </div>
  4166. </div>
  4167. </div>
  4168.  
  4169. </div>
  4170.  
  4171. <div id="pauseAdPlacement" ref="pauseAdPlacement"></div>
  4172. </template>
  4173. </large-popup>
  4174. </div>
  4175. <!-- .pause-popup--container -->
  4176.  
  4177. <!-- <div id="testbaby"></div> -->
  4178.  
  4179. </div>
  4180. <!-- end #inGameScaler -->
  4181.  
  4182. </div>
  4183. </script>
  4184.  
  4185. <script>
  4186. var comp_game_screen = {
  4187. template: '#game-screen-template',
  4188. components: {
  4189. 'account-panel': comp_account_panel,
  4190. },
  4191.  
  4192. data: function () {
  4193. return vueData;
  4194. },
  4195.  
  4196. created: function () {
  4197. window.addEventListener('resize', this.resizeBannerAdTagForGame);
  4198. },
  4199.  
  4200. destroyed: function () {
  4201. window.removeEventListener('resize', this.resizeBannerAdTagForGame);
  4202. },
  4203.  
  4204. methods: {
  4205. placeBannerAdTagForGame: function (tagEl) {
  4206. this.$refs.pauseAdPlacement.appendChild(tagEl);
  4207. },
  4208.  
  4209. showGameMenu: function () {
  4210. this.game.tipIdx = this.loc.tip_ofthe_day
  4211. ? Math.randomInt(0, this.loc.tip_ofthe_day.length)
  4212. : 0;
  4213. this.game.gameType = extern.gameType;
  4214. this.$refs.pausePopup.show();
  4215. vueData.ui.showCornerButtons = true;
  4216. setTimeout(() => this.resizeBannerAdTagForGame(), 1);
  4217. },
  4218.  
  4219. hideGameMenu: function () {
  4220. this.$refs.pausePopup.hide();
  4221. },
  4222.  
  4223. onHomeClicked: function () {
  4224. this.hideGameMenu();
  4225. this.$refs.leaveGameConfirmPopup.show();
  4226. vueApp.playSound('./sound/ui/ui_click.mp3');
  4227. },
  4228.  
  4229. onLeaveGameConfirm: function () {
  4230. this.leaveGame();
  4231. },
  4232.  
  4233. onLeaveGameCancel: function () {
  4234. this.showGameMenu();
  4235. },
  4236.  
  4237. leaveGame: function () {
  4238. // clientGame.js manipulates chickenBadge element directly to hide/show it
  4239. this.$refs.chickenBadge.style.display = 'none';
  4240.  
  4241. vueApp.showSpinner();
  4242. document.body.style.overflow = 'visible';
  4243. window.scrollY = 0;
  4244. this.hidePopupsIfGameCloses();
  4245. extern.leaveGame(this.afterLeftGame);
  4246. vueData.ui.showCornerButtons = true;
  4247. // OneSignal elements are not part of the Vue app
  4248. var oneSignalBell = document.getElementById('onesignal-bell-container');
  4249. if (oneSignalBell) {
  4250. oneSignalBell.style.display = 'inline-block';
  4251. }
  4252. },
  4253.  
  4254. hidePopupsIfGameCloses: function() {
  4255. const gamePopups = vueApp.$refs.gameScreen.$children;
  4256. if (Array.isArray(gamePopups)) {
  4257. gamePopups.forEach( gamePopup => {;
  4258. if ( gamePopup.isShowing === true && gamePopup.$el.id !== 'pausePopup' ) {
  4259. gamePopup.close();
  4260. console.log(`Closing ${gamePopup.$el.id}`);
  4261. }
  4262. });
  4263. }
  4264. },
  4265.  
  4266. afterLeftGame: function () {
  4267. vueApp.hideSpinner();
  4268. vueApp.switchToHomeUi();
  4269. },
  4270.  
  4271. onHelpClicked: function () {
  4272. this.hideGameMenu();
  4273. vueApp.showHelpPopup();
  4274. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  4275. },
  4276.  
  4277. onShareLinkClicked: function () {
  4278. extern.inviteFriends();
  4279. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  4280. },
  4281.  
  4282. onSettingsClicked: function () {
  4283. this.hideGameMenu();
  4284. vueApp.showSettingsPopup();
  4285. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  4286. },
  4287.  
  4288. onShareLinkConfirm: function () {
  4289. extern.copyFriendCode(this.$refs.shareLinkUrl);
  4290. },
  4291.  
  4292. onShareLinkClosed: function () {
  4293. this.showGameMenu();
  4294. },
  4295.  
  4296. onEquipClicked: function () {
  4297. this.hideGameMenu();
  4298. extern.openEquipInGame();
  4299. vueApp.switchToEquipUi();
  4300. vueApp.playSound('./sound/ui/ui_equip.mp3');
  4301. },
  4302.  
  4303. onSwitchTeamClicked: function () {
  4304. this.hideGameMenu();
  4305. vueApp.playSound('./sound/ui/ui_popupopen.mp3');
  4306. this.$refs.switchTeamPopup.show();
  4307. },
  4308.  
  4309. onSwitchTeamCancel: function () {
  4310. this.showGameMenu();
  4311. },
  4312.  
  4313. onSwitchTeamConfirm: function () {
  4314. extern.switchTeam();
  4315. this.showGameMenu();
  4316. },
  4317.  
  4318. onPlayClicked: function () {
  4319. this.hideGameMenu();
  4320. vueData.ui.showCornerButtons = false;
  4321. extern.respawn();
  4322. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  4323. },
  4324.  
  4325. onSpectateClicked: function () {
  4326. this.hideGameMenu();
  4327. vueData.ui.showCornerButtons = false;
  4328. extern.enterSpectatorMode();
  4329. vueApp.playSound('./sound/ui/ui_playconfirm.mp3');
  4330. },
  4331.  
  4332. showPlayerActionsPopup: function () {
  4333. this.hideGameMenu();
  4334. this.$refs.playerActionsPopup.show();
  4335. },
  4336.  
  4337. onPlayerActionsCancel: function () {
  4338. this.showGameMenu();
  4339. },
  4340.  
  4341. onMuteClicked: function () {
  4342. this.$refs.playerActionsPopup.hide();
  4343. this.playerActionsPopup.muteFunc();
  4344. },
  4345.  
  4346. onBootClicked: function () {
  4347. this.$refs.playerActionsPopup.hide();
  4348. this.playerActionsPopup.bootFunc();
  4349. },
  4350.  
  4351. resizeBannerAdTagForGame: function() {
  4352. const pauseAdPlacement = document.getElementById('pauseAdPlacement');
  4353. const rect = document.getElementById('pausePopup').getBoundingClientRect();
  4354.  
  4355. pauseAdPlacement.style.top = (rect.height).toString() + 'px';
  4356.  
  4357. if (rect.width < 970) {
  4358. pauseAdPlacement.style.transform = ' scale(' + (rect.width / 970) + ') translateX(-50%)';
  4359. } else {
  4360. pauseAdPlacement.style.transform = ' scale(1) translateX(-50%)';
  4361. }
  4362.  
  4363. }
  4364. },
  4365.  
  4366. computed: {
  4367. isRespawning: function () {
  4368. return this.game.respawnTime > 0;
  4369. },
  4370.  
  4371. isTeamGame: function () {
  4372. // Would be better to use the same enum as the client game code
  4373. return this.game.gameType !== 0;
  4374. },
  4375.  
  4376. teamColorCss: function () {
  4377. return this.game.team === this.ui.team.blue ? 'blueTeam btn_red bevel_red' : 'redTeam btn_blue bevel_blue';
  4378. },
  4379.  
  4380. teamName: function () {
  4381. return this.game.team === this.ui.team.blue ? this.loc.p_pause_joinred : this.loc.p_pause_joinblue;
  4382. },
  4383.  
  4384. newTeamColorCss: function () {
  4385. return this.game.team === this.ui.team.blue ? 'redTeam btn_red' : 'blueTeam btn_blue';
  4386. },
  4387.  
  4388. newTeamName: function () {
  4389. return this.game.team === this.ui.team.blue ? this.loc.team_red : this.loc.team_blue;
  4390. },
  4391.  
  4392. muteButtonLabel: function () {
  4393. return this.playerActionsPopup.muted ? this.loc.ui_game_playeractions_unmute : this.loc.ui_game_playeractions_mute;
  4394. }
  4395. }
  4396. };
  4397. </script>
  4398.  
  4399. <script>
  4400.  
  4401. function startVue(languageCode, locData) {
  4402.  
  4403. vueData.extern = extern;
  4404. vueData.loc = locData;
  4405.  
  4406. vueApp = new Vue({
  4407. el: '#app',
  4408. components: {
  4409. 'dark-overlay': comp_dark_overlay,
  4410. 'light-overlay': comp_light_overlay,
  4411. 'spinner-overlay': comp_spinner_overlay,
  4412. 'gdpr': comp_gdpr,
  4413. 'settings': comp_settings,
  4414. 'help': comp_help,
  4415. 'egg-store': comp_egg_store,
  4416. 'item': comp_item,
  4417. 'home-screen': comp_home_screen,
  4418. 'equip-screen': comp_equip_screen,
  4419. 'game-screen': comp_game_screen,
  4420. 'gold-chicken-popup': comp_gold_chicken_popup,
  4421. 'chicken-nugget-popup': comp_chicken_nugget_popup
  4422. },
  4423.  
  4424. data: vueData,
  4425.  
  4426. createdTime: null,
  4427. mountedTime: null,
  4428. fullyRenderedTime: null,
  4429.  
  4430. multisizeAdTag: null,
  4431.  
  4432. created () {
  4433. console.log('Vue instance created');
  4434. createdTime = performance.now();
  4435. // Create localStorage for language on vueApp created lifecyle if none present
  4436. if (! getStoredString('selectedLanguage', null) ){
  4437. localStorage.setItem('selectedLanguage', languageCode);
  4438. }
  4439. // currentLanguageCode is set the localStorage selecetedLanguage but just in case, set it to the default
  4440. this.currentLanguageCode = getStoredString('selectedLanguage', null) ? localStorage.getItem('selectedLanguage') : languageCode;
  4441. // run the method to update the current languge
  4442. this.changeLanguage(this.currentLanguageCode);
  4443. },
  4444.  
  4445. mounted () {
  4446. console.log('Vue instance mounted');
  4447. mountedTime = performance.now();
  4448. console.log('create -> mount time (ms): ' + (mountedTime - createdTime));
  4449.  
  4450. this.currentGameType = extern.gameType;
  4451.  
  4452. this.$options.multisizeAdTag = useAdManager
  4453. ? document.getElementById('div-gpt-ad-5141196-1')
  4454. : document.getElementById('shellshock-io_multisize');
  4455.  
  4456. // Cannot modify data within the mounted hook, so wait until next tick
  4457. this.$nextTick(function () {
  4458. fullyRenderedTime = performance.now();
  4459. console.log('mounted -> fully rendered time (ms): ' + (fullyRenderedTime - mountedTime));
  4460. console.log('created -> fully rendered time (ms): ' + (fullyRenderedTime - createdTime));
  4461.  
  4462. this.ready = true;
  4463.  
  4464. this.placeBannerAdTagForNugget(this.$options.multisizeAdTag);
  4465. this.showSpinner('ui_game_loading', 'ui_game_waitforit');
  4466. //this.playMusic();
  4467.  
  4468. extern.continueStartup();
  4469. });
  4470. },
  4471.  
  4472. methods: {
  4473. getCanvas: function () {
  4474. return this.$refs.canvas;
  4475. },
  4476.  
  4477. playMusic: function () {
  4478. myAudio = new Audio('./sound/theme.mp3');
  4479. // Uncomment for looping.
  4480. // myAudio.addEventListener('ended', function() {
  4481. // this.currentTime = 0;
  4482. // this.play();
  4483. // }, false);
  4484. myAudio.volume = this.volume;
  4485. myAudio.play();
  4486. },
  4487.  
  4488. playSound: function (sound) {
  4489. if(sound) {
  4490. var audio = new Audio(sound);
  4491. audio.volume = this.volume;
  4492. audio.play();
  4493. }
  4494. },
  4495.  
  4496. changeLanguage: function (languageCode) {
  4497. extern.getLanguageData(languageCode, this.setLocData);
  4498. },
  4499.  
  4500. setLocData: function (languageCode, newLocData) {
  4501. this.currentLanguageCode = getStoredString('selectedLanguage', null) ? localStorage.getItem('selectedLanguage') : languageCode;
  4502. this.loc = newLocData;
  4503. },
  4504.  
  4505. setPlayerName: function (playerName) {
  4506. this.playerName = playerName;
  4507. },
  4508.  
  4509. showSpinner: function (headerLocKey, footerLocKey) {
  4510. this.$refs.spinnerOverlay.show(headerLocKey, footerLocKey);
  4511. },
  4512.  
  4513. showSpinnerLoadProgress: function (percent) {
  4514. this.$refs.spinnerOverlay.showSpinnerLoadProgress(percent);
  4515. },
  4516.  
  4517. hideSpinner: function () {
  4518. this.$refs.spinnerOverlay.hide();
  4519. },
  4520.  
  4521. onSettingsPopupOpened: function () {
  4522. this.$refs.settings.captureOriginalSettings();
  4523. },
  4524.  
  4525. onSettingsX: function () {
  4526. this.$refs.settings.applyOriginalSettings();
  4527. this.$refs.settings.cancelLanguageSelect();
  4528. },
  4529.  
  4530. onNoAnonPopupConfirm: function () {
  4531. this.showFirebaseSignIn();
  4532. },
  4533.  
  4534. onSharedPopupClosed: function () {
  4535. // If in-game, show game menu after closing the popup
  4536. //this.playSound('./sound/ui/ui_popupclose.mp3');
  4537. if (this.ui.showScreen === this.ui.screens.game && extern.inGame) {
  4538. this.showGameMenu();
  4539. }
  4540. },
  4541.  
  4542. onGiveStuffComplete: function () {
  4543. this.$refs.giveStuffPopup.toggle();
  4544. },
  4545.  
  4546. onPrivacyOptionsOpened: function () {
  4547. this.showPrivacyPopup();
  4548. },
  4549. /**
  4550. * Creates a generic popup that passes content 3 data options to slots on the genericPopup smallPopup
  4551. * @param titleLockKey mixed - popup header text
  4552. * @param contentLocKey mixed- popup content
  4553. * @param confirmLocKey mixed - popup button text
  4554. */
  4555. showGenericPopup: function (titleLocKey, contentLocKey, confirmLocKey, hideBackgroundPopup) {
  4556. this.genericMessagePopup.titleLocKey = titleLocKey;
  4557. this.genericMessagePopup.contentLocKey = contentLocKey;
  4558. this.genericMessagePopup.confirmLocKey = confirmLocKey;
  4559. this.hidePausePopupIfGenericPopupOpen();
  4560. this.$refs.genericPopup.show();
  4561.  
  4562. // vueApp.setDarkOverlay();
  4563. },
  4564. hidePausePopupIfGenericPopupOpen: function() {
  4565.  
  4566. if (!this.$refs.gameScreen.$refs.pausePopup && $refs.gameScreen.$refs.pausePopup.isShowing === false) {
  4567. return;
  4568. }
  4569.  
  4570. return this.$refs.gameScreen.$refs.pausePopup.hide();
  4571. },
  4572. showOpenUrlPopup: function (url, titleLocKey, content, confirmLocKey, cancelLocKey) {
  4573. console.log('title: ' + this.loc[titleLocKey]);
  4574. console.log('confirm: ' + this.loc[confirmLocKey]);
  4575. console.log('cancel: ' + this.loc[cancelLocKey]);
  4576.  
  4577. this.openUrlPopup.url = url;
  4578. this.openUrlPopup.titleLocKey = titleLocKey;
  4579. this.openUrlPopup.content = content;
  4580. this.openUrlPopup.confirmLocKey = confirmLocKey;
  4581. this.openUrlPopup.cancelLocKey = cancelLocKey;
  4582. this.$refs.openUrlPopup.show();
  4583. },
  4584.  
  4585. onOpenUrlPopupConfirm: function () {
  4586. extern.openUrlAndGiveReward();
  4587. },
  4588.  
  4589. showMissingFeaturesPopup: function () {
  4590. this.ui.showScreen = -1;
  4591. this.$refs.missingFeaturesPopup.show();
  4592. },
  4593.  
  4594. showFirebaseSignIn: function () {
  4595. this.$refs.homeScreen.showSignIn();
  4596. },
  4597.  
  4598. hideFirebaseSignIn: function () {
  4599. this.$refs.homeScreen.$refs.firebaseSignInPopup.hide();
  4600. },
  4601.  
  4602. showCheckEmail: function () {
  4603. this.$refs.homeScreen.$refs.checkEmailPopup.show();
  4604. },
  4605.  
  4606. hideCheckEmail: function () {
  4607. this.$refs.homeScreen.$refs.checkEmailPopup.hide();
  4608. },
  4609.  
  4610. showResendEmail: function () {
  4611. this.$refs.homeScreen.$refs.resendEmailPopup.show();
  4612. },
  4613.  
  4614. hideResendEmail: function () {
  4615. this.$refs.homeScreen.$refs.resendEmailPopup.hide();
  4616. },
  4617.  
  4618. showChickenPopup: function () {
  4619. this.$refs.goldChickenPopup.show();
  4620. },
  4621.  
  4622. hideChickenPopup: function () {
  4623. this.$refs.goldChickenPopup.hide();
  4624. },
  4625.  
  4626. showHelpPopup: function () {
  4627. this.hideGameMenu();
  4628. this.$refs.helpPopup.show();
  4629. },
  4630.  
  4631. showAttentionPopup: function () {
  4632. this.hideGameMenu();
  4633. this.$refs.anonWarningPopup.show();
  4634. },
  4635.  
  4636. hideHelpPopup: function () {
  4637. this.$refs.helpPopup.hide();
  4638. },
  4639.  
  4640. showSettingsPopup: function () {
  4641. this.hideGameMenu();
  4642. this.$refs.settingsPopup.show();
  4643. extern.settingsMenuOpened();
  4644. },
  4645.  
  4646. hideSettingsPopup: function () {
  4647. this.$refs.settingsPopup.hide();
  4648. },
  4649.  
  4650. showEggStorePopup: function () {
  4651. this.hideGameMenu();
  4652. this.$refs.eggStorePopup.show();
  4653. },
  4654.  
  4655. hideEggStorePopup: function () {
  4656. this.$refs.eggStorePopup.hide();
  4657. },
  4658.  
  4659. showChangelogPopup: function () {
  4660. this.$refs.changelogPopup.show();
  4661. },
  4662.  
  4663. hideChangelogPopup: function () {
  4664. //this.playSound('./sound/ui/ui_popupclose.mp3');
  4665. this.$refs.changelogPopup.hide();
  4666. },
  4667.  
  4668. showGiveStuffPopup: function (titleLoc, eggs, items) {
  4669. this.giveStuffPopup.titleLoc = titleLoc;
  4670. this.giveStuffPopup.eggs = eggs;
  4671. this.giveStuffPopup.items = items;
  4672. this.$refs.giveStuffPopup.show();
  4673. },
  4674.  
  4675. showShareLinkPopup: function (url) {
  4676. this.hideGameMenu();
  4677. this.game.shareLinkPopup.url = url;
  4678. this.$refs.gameScreen.$refs.shareLinkPopup.show();
  4679. },
  4680.  
  4681. showJoinPrivateGamePopup: function (code) {
  4682. this.$refs.homeScreen.$refs.playPanel.showJoinPrivateGamePopup(code);
  4683. },
  4684.  
  4685. switchToHomeUi: function () {
  4686. this.ui.showScreen = this.ui.screens.home;
  4687.  
  4688. this.placeBannerAdTagForNugget(vueApp.$options.multisizeAdTag);
  4689. },
  4690.  
  4691. switchToEquipUi: function () {
  4692. console.log('switchToEquipUi called');
  4693. this.$refs.equipScreen.setup();
  4694. this.$refs.equipScreen.switchToInventory();
  4695. this.ui.showScreen = this.ui.screens.equip;
  4696. },
  4697.  
  4698. switchToGameUi: function (isGameOwner) {
  4699. this.ui.showScreen = this.ui.screens.game;
  4700. this.game.isGameOwner = isGameOwner;
  4701.  
  4702. // The ad tags are outside of the Vue app; manipulate the DOM directly
  4703. this.$refs.gameScreen.placeBannerAdTagForGame(vueApp.$options.multisizeAdTag);
  4704.  
  4705. this.showGameMenu();
  4706. },
  4707.  
  4708. showGameMenu: function () {
  4709. this.hideSpinner();
  4710. this.$refs.gameScreen.showGameMenu();
  4711. },
  4712.  
  4713. hideGameMenu: function () {
  4714. this.$refs.gameScreen.hideGameMenu();
  4715. },
  4716.  
  4717. onMiniGameCompleted: function () {
  4718. this.$refs.homeScreen.onMiniGameCompleted();
  4719. },
  4720.  
  4721. setShellColor: function (colorIdx) {
  4722. this.equip.colorIdx = colorIdx;
  4723. },
  4724.  
  4725. setAccountUpgraded: function (upgraded) {
  4726. this.isUpgraded = upgraded;
  4727. this.equip.extraColorsLocked = !this.isUpgraded;
  4728. },
  4729.  
  4730. setDarkOverlay: function (visible, overlayClass) {
  4731. this.$refs.darkOverlay.show = visible;
  4732. this.$refs.darkOverlay.overlayClass = overlayClass;
  4733. },
  4734.  
  4735. setLightOverlay: function (visible, overlayClass) {
  4736. this.$refs.lightOverlay.show = visible;
  4737. this.$refs.darkOverlay.overlayClass = overlayClass;
  4738. },
  4739.  
  4740. authCompleted: function () {
  4741. this.hideFirebaseSignIn();
  4742. if (extern.isGameReady) {
  4743. this.hideSpinner();
  4744. this.setDarkOverlay(false);
  4745. }
  4746. },
  4747.  
  4748. showItemOnEquipScreen: function (item) {
  4749. this.switchToEquipUi();
  4750. this.$refs.equipScreen.autoSelectItem(item);
  4751. },
  4752.  
  4753. showTaggedItemsOnEquipScreen: function (tag) {
  4754. this.switchToEquipUi();
  4755. this.$refs.equipScreen.showTaggedItems(tag);
  4756. },
  4757.  
  4758. useHouseAdSmall: function (smallHouseAd) {
  4759. this.ui.houseAds.small = smallHouseAd;
  4760. },
  4761.  
  4762. useHouseAdBig: function (bigHouseAd) {
  4763. this.ui.houseAds.big = bigHouseAd;
  4764. },
  4765.  
  4766. denyAnonUser: function () {
  4767. this.$refs.noAnonPopup.show();
  4768. },
  4769.  
  4770. showGdrpNotification: function () {
  4771. this.$refs.gdpr.show();
  4772. },
  4773.  
  4774. showPrivacyPopup: function () {
  4775. this.hideSettingsPopup();
  4776. this.$refs.privacyPopup.show();
  4777. },
  4778.  
  4779. hidePrivacyPopup: function () {
  4780. this.$refs.privacyPopup.hide();
  4781. this.showSettingsPopup();
  4782. },
  4783.  
  4784. ofAgeChanged: function () {
  4785. extern.setOfAge(this.isOfAge);
  4786. this.playSound('./sound/ui/ui_onchange.mp3');
  4787. },
  4788.  
  4789. targetedAdsChanged: function () {
  4790. extern.setTargetedAds(this.showTargetedAds);
  4791. this.playSound('./sound/ui/ui_onchange.mp3');
  4792. },
  4793.  
  4794. setPrivacySettings: function (ofAge, targetedAds) {
  4795. this.isOfAge = ofAge;
  4796. this.showTargetedAds = targetedAds;
  4797. },
  4798.  
  4799. gameJoined: function (gameType, team) {
  4800. this.game.gameType = gameType;
  4801. this.setTeam(team);
  4802. },
  4803.  
  4804. setTeam: function (team) {
  4805. if (hasValue(team)) {
  4806. this.game.team = team;
  4807. }
  4808. },
  4809.  
  4810. showGoldChickenPopup: function () {
  4811. this.$refs.goldChickenPopup.show();
  4812. },
  4813.  
  4814. hideGoldChickenPopup: function () {
  4815. this.$refs.goldChickenPopup.hide();
  4816. },
  4817.  
  4818. showNuggetPopup: function () {
  4819. this.$refs.nuggetPopup.show();
  4820. this.$refs.chickenNugget.loadMiniGame();
  4821. },
  4822.  
  4823. hideNuggetPopup: function () {
  4824. this.$refs.nuggetPopup.hide();
  4825. this.$refs.chickenNugget.unloadMiniGame();
  4826. },
  4827.  
  4828. onMiniGameCompleted: function () {
  4829. this.$refs.chickenNugget.onMiniGameCompleted();
  4830. },
  4831.  
  4832. placeBannerAdTagForNugget: function (tagEl) {
  4833. this.$refs.chickenNugget.placeBannerAdTag(tagEl);
  4834. },
  4835.  
  4836. useSpecialItemsTag: function (tag) {
  4837. this.equip.specialItemsTag = tag;
  4838. this.equip.showSpecialItems = true;
  4839. },
  4840.  
  4841. disableSpecialItems: function () {
  4842. this.equip.showSpecialItems = false;
  4843. },
  4844.  
  4845. setUiSettings: function (settings) {
  4846. this.$refs.settings.setSettings(settings);
  4847. },
  4848.  
  4849. leaveGame: function () {
  4850. this.$refs.gameScreen.leaveGame();
  4851. },
  4852.  
  4853. showPlayerActionsPopup: function (slot) {
  4854. this.playerActionsPopup = slot;
  4855. this.$refs.gameScreen.showPlayerActionsPopup();
  4856. },
  4857. anonWarningPopupConfrim: function() {
  4858. const anonWarnConfrimed = localStorage.getItem('anonWarningConfirmed');
  4859. return anonWarnConfrimed === null && localStorage.setItem('anonWarningConfirmed', true);
  4860. },
  4861. conditionalAnonWarningCall: function() {
  4862. const anonWarnConfrimed = localStorage.getItem('anonWarningConfirmed');
  4863. return anonWarnConfrimed === null && vueApp.showAttentionPopup();
  4864. },
  4865. needMoreEggsPopupCall: function() {
  4866. this.$refs.needMoreEggsPopup.show();
  4867. }
  4868. }
  4869. });
  4870. }
  4871. </script>
  4872. </body>
  4873. </html>

Source Code

Nend.io

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Nend.io</title>
  5. <meta charset="utf-8" />
  6. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  7. <meta name="description" content="Survive to the city, upgrade your skill, live, age and prepare the next generation"/>
  8. <meta name="keywords" content="nend.io, mmo, online game, flash, canvas, html5, nend, life, city, life simulation, age, baby, family, street"/>
  9. <meta property="og:title" content="Nend.io - The Never Ending game"/>
  10. <meta property="og:description" content="Survive to city! Live, age and prepare the next generation."/>
  11. <meta property="og:url" content="https://nend.io"/>
  12. <meta property="og:site_name" content="nend.io"/>
  13. <meta property="og:image" content="https://nend.io/img/banner.png"/>
  14. <meta property="og:image:width" content="849"/>
  15. <meta property="og:image:height" content="488"/>
  16. <meta name="twitter:card" content="summary_large_image"/>
  17. <meta name="twitter:site" content="@nendio"/>
  18. <meta name="twitter:creator" content="@lapamauve"/>
  19. <meta name="twitter:url" content="https://nend.io"/>
  20. <meta name="twitter:title" content="Nend.io - The Never Ending game"/>
  21. <meta name="twitter:description" content="Survive to city! Live, age and prepare the next generation."/>
  22. <meta name="twitter:image" content="https://nend.io/img/banner.png"/>
  23. <meta name="mobile-web-app-capable" content="yes"/>
  24. <meta name="apple-mobile-web-app-capable" content="yes"/>
  25. <meta name="robots" content="index, follow"/>
  26. <meta name="revisit-after" content="3 days"/>
  27. <meta name="googlebot" content="all"/>
  28. <link rel="icon" type="image/png" href="img/favicon.png"/>
  29. <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:500,700"/>
  30. <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Press+Start+2P"/>
  31. <link rel="stylesheet" type="text/css" href="css/style.css"/>
  32. </head>
  33.  
  34. <body id="bod">
  35.  
  36. <canvas id="can"></canvas>
  37.  
  38. <script src="js/client.1.2009.min.js"></script>
  39.  
  40. <div id="nickname">
  41.  
  42. <input id="nicknameInput" type="text" placeholder="Nickname" maxLength="16">
  43.  
  44. </div>
  45.  
  46. <div id="play">
  47.  
  48. <div id="playButton"> PLAY </div>
  49.  
  50. </div>
  51.  
  52. <div id="seeMore">
  53.  
  54. <a style="text-decoration: none; color : #595388;" href="./changelog/" target="_blank">
  55. <div class="seeMoreActive">SEE MORE</div>
  56. </a>
  57.  
  58. </div>
  59.  
  60. <div id="terms">
  61.  
  62. <a class="link" href="http://nend.io/termsofuse" target="blank">Terms of Use</a> - <a class="link" href="http://nend.io/privacy" target="blank">Privacy</a>
  63.  
  64. </div>
  65.  
  66. <div id="serverList">
  67.  
  68. <select id="servers">
  69. <option disabled>Paris 3000 players</option>
  70. <option>Paris - 200 players</option>
  71. <option>Paris - 2800 players</option>
  72. </select>
  73.  
  74. </div>
  75.  
  76. <div id="howtoplay">
  77.  
  78. HOW TO PLAY ?
  79. <br /><br />
  80.  
  81. <div id="resumeHowToPlay">
  82. <div class="resume"> The city survival game:</div>
  83. <div class="resume"> Upgrade your skills </div>
  84. <div class="resume"> Buy and sell buildings</div>
  85. <div class="resume"> Be the richest</div>
  86. </div>
  87.  
  88. <br />
  89. COMMANDS
  90. <br /><br />
  91.  
  92. <div id="commandsHowToPlay">
  93. <div class="commands"> <span id="arrowHowToPlay" class="subcommands">ARROW KEY</span> or <span id="wasdHowToPlay"class="subcommands">WASD</span> to move </div>
  94. <div class="commands"> <span id="leftHowToPlay" class="subcommands">LEFT CLICK</span> to hit</div>
  95. <div class="commands"> <span id="enterHowToPlay"class="subcommands">ENTER</span> to chat</div>
  96. <div class="commands"> <span id="eHowToPlay" class="subcommands">E</span> or <span id="spaceHowToPlay" class="subcommands">SPACE</span> to interact</div>
  97. <div class="commands"> <span id="mHowToPlay" class="subcommands">M</span> for Map</div>
  98. <div class="commands"> <span id="rightHowToPlay" class="subcommands">RIGHT CLICK</span> to delete items</div>
  99.  
  100. <br /><br />
  101.  
  102. </div>
  103.  
  104. <!-- Global site tag (gtag.js) - Google Analytics -->
  105. <script async src="https://www.googletagmanager.com/gtag/js?id=UA-78561996-4"></script>
  106. <script>
  107. window.dataLayer = window.dataLayer || [];
  108. function gtag(){dataLayer.push(arguments);}
  109. gtag('js', new Date());
  110.  
  111. gtag('config', 'UA-78561996-4');
  112. </script>
  113.  
  114. </div>
  115.  
  116. <div id="otherGames">
  117.  
  118. Our Other Games
  119.  
  120. </div>
  121.  
  122. <div id="authors">
  123.  
  124. <a class="link" href="http://nend.io/authors" target="blank" style="color: #EEC0FD;font-weight: 900;">Authors</a> -
  125.  
  126. </div>
  127.  
  128. <div id="advert">
  129.  
  130. <script async src="//api.adinplay.com/player/v2/NND/nend.io/player.min.js"></script>
  131. <script async src="//api.adinplay.com/display/pub/NND/nend.io/display.min.js"></script>
  132. <div id='nend-io_300x250'>
  133. <script type='text/javascript'>
  134. var aiptag = aiptag || {};
  135. aiptag.cmd = aiptag.cmd || [];
  136. aiptag.cmd.display = aiptag.cmd.display || [];
  137. aiptag.cmd.display.push(function() { aipDisplayTag.display('nend-io_300x250'); });
  138. </script>
  139. </div>
  140.  
  141. </div>
  142.  
  143. <div id="preroll">
  144.  
  145. </div>
  146.  
  147. <div id="chat">
  148.  
  149. <input id="chatInput" type="text" placeholder="Enter text..." maxLength="60">
  150.  
  151. </div>
  152.  
  153. </body>
  154. </html>

Source Code

Hexarena.io

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta
  6. name="description"
  7. content="HexArena.io is a 100% free multiplayer, live action, strategy game."
  8. />
  9. <meta
  10. property="og:description"
  11. content="HexArena.io is a 100% free multiplayer, live action, strategy game."
  12. />
  13. <meta property="og:title" content="HexArena.io" />
  14. <meta property="og:url" content="https://hexarena.io" />
  15. <meta
  16. property="og:image"
  17. content="https://hexarena.io/static/images/og-image.png"
  18. />
  19. <meta property="og:image:width" content="1200" />
  20. <meta property="og:image:height" content="630" />
  21. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  22. <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  23. <title>HexArena.io</title>
  24. <link rel="icon" type="image/x-icon" href="/static/favicon/96x96.png" />
  25. <link
  26. href="https://fonts.googleapis.com/css?family=Montserrat:200,300,400,500,600,700'"
  27. rel="stylesheet"
  28. />
  29.  
  30. <!-- Sentry -->
  31. <script
  32. src="https://browser.sentry-cdn.com/5.0.7/bundle.min.js"
  33. crossOrigin="anonymous"
  34. ></script>
  35. <script>
  36. const getEnvironment = () => {
  37. switch (window.location.hostname) {
  38. case 'localhost':
  39. return 'local'
  40. case 'dev.hexarena.io':
  41. return 'development'
  42. case 'hexarena.io':
  43. return 'production'
  44. default:
  45. return 'unknown-environment'
  46. }
  47. }
  48. Sentry.init({
  49. dsn: 'https://28bb77120c0b45a991f6c251a58ffa63@sentry.io/1438180',
  50. environment: getEnvironment(),
  51. })
  52. </script>
  53.  
  54. <!-- Google Analytics -->
  55. <script
  56. async
  57. src="https://www.googletagmanager.com/gtag/js?id=UA-68180597-3"
  58. ></script>
  59. <script>
  60. window.dataLayer = window.dataLayer || []
  61. function gtag() {
  62. dataLayer.push(arguments)
  63. }
  64. gtag('js', new Date())
  65. gtag('config', 'UA-68180597-3')
  66. </script>
  67.  
  68. <!-- Facebook SDK -->
  69. <script>
  70. window.fbAsyncInit = function() {
  71. FB.init({
  72. appId: '2146819318950261',
  73. cookie: true,
  74. xfbml: true,
  75. version: 'v3.3',
  76. })
  77.  
  78. FB.AppEvents.logPageView()
  79. }
  80. ;(function(d, s, id) {
  81. var js,
  82. fjs = d.getElementsByTagName(s)[0]
  83. if (d.getElementById(id)) {
  84. return
  85. }
  86. js = d.createElement(s)
  87. js.id = id
  88. js.src = 'https://connect.facebook.net/en_US/sdk.js'
  89. fjs.parentNode.insertBefore(js, fjs)
  90. })(document, 'script', 'facebook-jssdk')
  91. </script>
  92. </head>
  93.  
  94. <body>
  95. <div id="root"></div>
  96. <script type="text/javascript" src="bundle.1.53.3.js"></script></body>
  97. </html>

Source Code

Update more in the few days

Website's Game source code的更多相关文章

  1. Tips for newbie to read source code

    This post is first posted on my WeChat public account: GeekArtT Reading source code is always one bi ...

  2. How to build the Robotics Library from source code on Windows

    The Robotics Library is an open source C++ library for robot kinematics, motion planning and control ...

  3. [转]Native Java Bytecode Debugging without Source Code

    link from:http://www.crowdstrike.com/blog/native-java-bytecode-debugging-without-source-code/index.h ...

  4. 编程等宽字体Source Code Pro(转)

    Source Code Pro - 最佳的免费编程字体之一!来自 Adobe 公司的开源等宽字体下载     每一位程序员都有一套自己喜爱的代码编辑器与编程字体,譬如我们之前就推荐过一款"神 ...

  5. How to build windows azure PowerShell Source Code

    Download any version source code of Windows Azure Powershell from https://github.com/Azure/azure-sdk ...

  6. akka cluster sharding source code 学习 (1/5) 替身模式

    为了使一个项目支持集群,自己学习使用了 akka cluster 并在项目中实施了,从此,生活就变得有些痛苦.再配上 apache 做反向代理和负载均衡,debug 起来不要太酸爽.直到现在,我还对 ...

  7. view class source code with JAD plugin in Eclipse

    The default class viewer doesn't decompile the class file so you cannot open and check the source co ...

  8. Classic Source Code Collected

    收藏一些经典的源码,持续更新!!! 1.深度学习框架(Deep Learning Framework). A:Caffe (Convolutional Architecture for Fast Fe ...

  9. Attach source code to a Netbeans Library Wrapper Module

    http://rubenlaguna.com/wp/2008/02/22/attach-source-code-to-a-netbeans-library-wrapper-module/ Attach ...

随机推荐

  1. selenium+python自动化用例登陆界面模板

    一.基本逻辑 1.自动填写用户名和密码登录成功后跳转到相应页面 2.验证相应页面的url与给定的url是否一致,如果一致则测试通过,如果不一致则不通过 二.以jenkins登陆界面为例,代码如下 fr ...

  2. 2017年陕西省网络空间安全技术大赛——一维码——Writeup

    <!doctype html> 2017年陕西省网络空间安全技术大赛——一维码——Writeup 先判断下载的文件flag.png确实是png格式的图片后(binwalk, file命令均 ...

  3. Hadoop架构: 流水线(PipeLine)

    该系列总览: Hadoop3.1.1架构体系——设计原理阐述与Client源码图文详解 : 总览 流水线(PipeLine),简单地理解就是客户端向DataNode传输数据(Packet)和接收Dat ...

  4. CSS3的一个伪类选择器:nth-child()

    CSS3的一个伪类选择器“:nth-child()”. Table表格奇偶数行定义样式: 语法: :nth-child(an+b) 为什么选择她,因为我认为,这个选择器是最多学问的一个了.很可惜,据我 ...

  5. 编译原理--05 用C++手撕PL/0

    前言 目录 01 文法和语言.词法分析复习 02 自顶向下.自底向上的LR分析复习 03 语法制导翻译和中间代码生成复习 04 符号表.运行时存储组织和代码优化复习 05 用C++手撕PL/0 在之前 ...

  6. 清晰架构(Clean Architecture)的Go微服务: 程序设计

    我使用Go和gRPC创建了一个微服务,并将程序设计和编程的最佳实践应用于该项目. 我写了一系列关于在项目工作中做出的设计决策和取舍的文章,此篇是关于程序设计. 程序的设计遵循清晰架构(Clean Ar ...

  7. 最漂亮的Spring事务管理详解

    SnailClimb 2018年05月21日阅读 7245 可能是最漂亮的Spring事务管理详解 Java面试通关手册(Java学习指南):github.com/Snailclimb/- 微信阅读地 ...

  8. 包、logging模块、hashlib模块、openpyxl模块、深浅拷贝

    包.logging模块.hashlib模块.openpyxl模块.深浅拷贝 一.包 1.模块与包 模块的三种来源: 1.内置的 2.第三方的 3.自定义的 模块的四种表现形式: 1.py文件 2.共享 ...

  9. 【PAT甲级】1090 Highest Price in Supply Chain (25 分)

    题意: 输入一个正整数N(<=1e5),和两个小数r和f,表示树的结点总数和商品的原价以及每向下一层价格升高的幅度.下一行输入N个结点的父结点,-1表示为根节点.输出最深的叶子结点处购买商品的价 ...

  10. IDEA自动部署WEB工程至远程服务器(学习笔记)

    一.部署Web工程的几种方式 ①本地打war,上传至远程服务器tomcat容器即可 优点:简单粗暴 缺点:浪费时间 ②IDEA自动部署至远程服务器 优点:节省大量时间 缺点:配置稍多(第一次) 二.I ...