From: neauoire Date: Thu, 16 Apr 2020 10:53:23 +0000 (+0900) Subject: Added old files X-Git-Url: https://stephenjianu.com/gitweb/?a=commitdiff_plain;p=donsol-js.git Added old files --- diff --git a/icon.icns b/icon.icns new file mode 100644 index 0000000..ea8b11c Binary files /dev/null and b/icon.icns differ diff --git a/icon.ico b/icon.ico new file mode 100644 index 0000000..d6ceaa3 Binary files /dev/null and b/icon.ico differ diff --git a/main.js b/main.js new file mode 100644 index 0000000..44febaf --- /dev/null +++ b/main.js @@ -0,0 +1,76 @@ +const { app, BrowserWindow, webFrame, Menu, dialog } = require('electron') +const path = require('path') +const url = require('url') +const shell = require('electron').shell + +let isShown = true + +app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required') + +app.on('ready', () => { + app.win = new BrowserWindow({ + width: 860, + height: 420, + minWidth: 860, + minHeight: 420, + backgroundColor: '#000', + icon: path.join(__dirname, { darwin: 'icon.icns', linux: 'icon.png', win32: 'icon.ico' }[process.platform] || 'icon.ico'), + resizable: true, + frame: process.platform !== 'darwin', + skipTaskbar: process.platform === 'darwin', + autoHideMenuBar: process.platform === 'darwin', + webPreferences: { zoomFactor: 1.0, nodeIntegration: true, backgroundThrottling: false } + }) + + app.win.loadURL(`file://${__dirname}/sources/index.html`) + // app.inspect(); + + app.win.on('closed', () => { + win = null + app.quit() + }) + + app.win.on('hide', function () { + isShown = false + }) + + app.win.on('show', function () { + isShown = true + }) + + app.on('window-all-closed', () => { + app.quit() + }) + + app.on('activate', () => { + if (app.win === null) { + createWindow() + } else { + app.win.show() + } + }) +}) + +app.inspect = function () { + app.win.toggleDevTools() +} + +app.toggle_fullscreen = function () { + app.win.setFullScreen(!app.win.isFullScreen()) +} + +app.toggle_visible = function () { + if (process.platform == 'win32') { + if (!app.win.isMinimized()) { app.win.minimize() } else { app.win.restore() } + } else { + if (isShown && !app.win.isFullScreen()) { app.win.hide() } else { app.win.show() } + } +} + +app.inject_menu = function (menu) { + try { + Menu.setApplicationMenu(Menu.buildFromTemplate(menu)) + } catch (err) { + console.warn('Cannot inject menu.') + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..9b54b72 --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "Donsol", + "version": "0.1.0", + "main": "main.js", + "scripts": { + "start": "electron .", + "clean": "rm -r ~/Desktop/Donsol-darwin-x64/ ; rm -r ~/Desktop/Donsol-linux-x64/ ; rm -r ~/Desktop/Donsol-win32-x64/ ; rm -r ~/Desktop/Donsol-linux-armv7l/ ; echo 'cleaned build location'", + "build_osx": "electron-packager . Donsol --platform=darwin --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.icns ; echo 'Built for OSX'", + "build_linux": "electron-packager . Donsol --platform=linux --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.ico ; echo 'Built for LINUX'", + "build_win": "electron-packager . Donsol --platform=win32 --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.ico ; echo 'Built for WIN'", + "build_pi": "electron-packager . Donsol --platform=linux --arch=armv7l --out ~/Desktop/ --overwrite --icon=icon.ico ; echo 'Built for PI'", + "build": "npm run clean ; npm run build_osx ; npm run build_linux ; npm run build_win", + "push_osx": "~/butler push ~/Desktop/Donsol-darwin-x64/ hundredrabbits/donsol:osx-64", + "push_linux": "~/butler push ~/Desktop/Donsol-linux-x64/ hundredrabbits/donsol:linux-64", + "push_win": "~/butler push ~/Desktop/Donsol-win32-x64/ hundredrabbits/donsol:windows-64", + "push_pi": "~/butler push ~/Desktop/Donsol-linux-armv7l/ hundredrabbits/donsol:linux-pi", + "push_status": "~/butler status hundredrabbits/donsol", + "push_theme": "~/butler push ~/Github/HundredRabbits/Themes/themes/ hundredrabbits/donsol:themes", + "push": "npm run build ; npm run push_theme ; npm run push_osx ; npm run push_linux ; npm run push_win ; npm run clean ; npm run push_status" + }, + "devDependencies": { + "electron": "^7.1.12", + "electron-packager": "^14.2.1" + } +} diff --git a/sources/index.html b/sources/index.html new file mode 100644 index 0000000..9560a1e --- /dev/null +++ b/sources/index.html @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Donsol + + +
+
+
+
+ 1 + 2 + 3 + 4 +
+
+ + + diff --git a/sources/links/fonts.css b/sources/links/fonts.css new file mode 100644 index 0000000..be688de --- /dev/null +++ b/sources/links/fonts.css @@ -0,0 +1,15 @@ +/* Input */ + +@font-face { + font-family: 'input_mono_regular'; + src: url('../media/fonts/input_mono_regular.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'input_mono_medium'; + src: url('../media/fonts/input_mono_medium.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} \ No newline at end of file diff --git a/sources/links/main.css b/sources/links/main.css new file mode 100644 index 0000000..b127901 --- /dev/null +++ b/sources/links/main.css @@ -0,0 +1,37 @@ +body { background:black; font-family: 'input_mono_regular',monospace; min-width:750px; overflow-y: hidden; user-select: none; cursor: default; -webkit-app-region: drag; padding:30px;} + +#wrapper { display: block;max-width: 900px; height: calc(25vw * 1.25 + 90px);max-height:400px;margin:0px auto;position: relative;width:100%; -webkit-app-region: drag;} + +#player { display: block; font-size:12px; height:30px; line-height:20px; max-width:890px; -webkit-user-select: none;-webkit-app-region: drag; position: fixed; bottom:30px; width:calc(100% - 60px);} +#player > * { vertical-align: top } +#player .gage { width: 120px;display: block;height:30px;position: relative; float:right; margin-left:2px;width:70px; padding-right: 50px; text-align: right} +#player .gage .value { display: inline-block;line-height: 20px;font-family: 'input_mono_medium';padding-left: 5px;} +#player .gage .event { display: inline-block;position: absolute;top: -20px;left: 0px; transition: all 250ms; opacity: 0; margin-left:5px; display: none} +#player .gage .progress { display: block;width: 40px;position: absolute; top:7px;overflow: hidden;height: 4px;border-radius: 20px;right:0px;} +#player .gage .progress .bar{ height:5px; display:block !important; transition: width 300ms} +#player a.escape { -webkit-app-region: no-drag;padding: 0px 8px;border-radius: 20px;display: inline-block;margin-right: 10px;line-height: 20px; border:2px solid white; margin-top:0px; color:white;} +#player a.escape:hover { cursor: pointer; } +#player div#timeline { display: inline-block;color:white; transition: opacity 250ms; opacity: 0 } +#player div#timeline b { font-family: 'input_mono_medium',monospace; } + +#player.locked a.escape { display:none;} + +#board, #table { display:block; position: absolute; width: calc(100% + 15px)} +#board card, #table card { display: inline-block !important;height: calc(25vw * 1.25);max-height:300px;max-width:200px;width: calc(25% - 15px);margin-right: 15px;border-radius: 7px; position:relative; overflow:hidden;min-height: 300px;} +#board card { top:10px; opacity:0.01; z-index:900; transition: opacity 250ms, top 150ms } +#board card:hover { cursor:pointer; top:5px !important;} +#board card .face { display:block;width: 100%;height: calc(100% - 5px);border-radius: 7px;} +#board card .face img { width:100%; position: absolute;bottom:0px; } +#board card .face .value { display: block;position: absolute;width: 30px;height: 30px;left: 15px;top: 60px;font-size: 12px;text-align: center;} +#board card .face .graphic svg { display: block;position: absolute;left: calc(50% - 100px);bottom: calc(50% - 150px);} +#board card .face .icon { display: block;position: absolute;width: 30px;height: 30px;left: 15px;top: 15px;font-size: 11px; z-index:900;} +#board card .face .name { display: block;position: absolute;bottom: 20px;text-align: center;font-size: 11px;width: 100%;} + +#table card { } +#table card .shortcut { position:absolute; right:20px; bottom:15px; color:#555;} + +#board card:nth-child(2), #table card:nth-child(2) { position:absolute; left:25%;} +#board card:nth-child(3), #table card:nth-child(3) { position:absolute; left:50%;} +#board card:nth-child(4), #table card:nth-child(4) { position:absolute; left:75%;} + +#difficulty:hover { text-decoration: underline; cursor: pointer; } \ No newline at end of file diff --git a/sources/links/reset.css b/sources/links/reset.css new file mode 100644 index 0000000..9f57584 --- /dev/null +++ b/sources/links/reset.css @@ -0,0 +1 @@ +* { margin:0;padding:0;border:0;outline:0;text-decoration:none;font-weight:inherit;font-style:inherit;color:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;list-style:none;border-collapse:collapse;border-spacing:0; -webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;} \ No newline at end of file diff --git a/sources/links/theme.css b/sources/links/theme.css new file mode 100644 index 0000000..9430a8b --- /dev/null +++ b/sources/links/theme.css @@ -0,0 +1,54 @@ +body { background-color:var(--background) !important }; +.fh { color:var(--f_high) !important; stroke:var(--f_high) !important }; +.fm { color:var(--f_med) !important ; stroke:var(--f_med) !important }; +.fl { color:var(--f_low) !important ; stroke:var(--f_low) !important }; +.f_inv { color:var(--f_inv) !important ; stroke:var(--f_inv) !important }; +.bh { background-color:var(--b_high) !important; fill:var(--b_high) !important }; +.bm { background-color:var(--b_med) !important ; fill:var(--b_med) !important }; +.bl { background-color:var(--b_low) !important ; fill:var(--b_low) !important }; +.b_inv { background-color:var(--b_inv) !important ; fill:var(--b_inv) !important }; +.b { background-color:var(--background) !important; } + +/* Donsol Theme Scheme */ + +/* Red */ +svg .fill_red { fill:var(--f_med) !important } +#board card.heart .face { color:var(--f_med) !important;} +#board card.diamond .face { color:var(--f_med) !important;} + +/* Black */ +svg .fill_black { fill:var(--f_high) !important } +#board card.clove .face { color:var(--f_high) !important;} +#board card.spade .face { color:var(--f_high) !important;} +#board card.joker .face { color:var(--f_high) !important;} +svg .stroke_black { stroke:var(--f_high) !important } + +/* Grey */ +svg .stroke_grey { stroke:var(--f_low) !important } +svg .fill_grey { opacity:0.25; fill:var(--f_low) !important } + +/* White */ +svg .fill_white { fill:var(--b_high) !important } +#player a.escape { border:2px solid var(--b_high) !important; color: var(--b_high); } +#player a.escape:hover { background-color:var(--b_high) !important; color:var(--background); } +#board card .face { background-color:var(--b_high)} +.card_11 .face .name,.card_13 .face .name,.card_15 .face .name,.card_17 .face .name { color:var(--b_high);} +#player .gage { color:var(--b_high) } +svg .stroke_white { stroke:var(--b_high) !important } + +/* Dark Grey */ +#table card { background-color:var(--b_low) !important} +#player .gage .value .unit { color:var(--b_low) !important} +#player .gage .progress { background-color:var(--b_low) !important } + +/* EXTRAS*/ +#player .gage.health .progress .bar { background-color:var(--b_inv) !important } +#player .gage.shield .progress .bar { background-color:var(--b_high) !important } +#player .gage.experience .progress .bar { background-color:var(--b_med) !important } +#table card .shortcut { color:var(--background) !important} +#difficulty { color:var(--f_high) !important } + +/* DEATH*/ + +#player.death a.escape { border-color:var(--b_inv) !important; } +#player.death a.escape:hover { background-color:var(--b_inv) !important; } \ No newline at end of file diff --git a/sources/media/audio/effect/click1.ogg b/sources/media/audio/effect/click1.ogg new file mode 100644 index 0000000..76c0125 Binary files /dev/null and b/sources/media/audio/effect/click1.ogg differ diff --git a/sources/media/audio/effect/click2.ogg b/sources/media/audio/effect/click2.ogg new file mode 100644 index 0000000..8a9a061 Binary files /dev/null and b/sources/media/audio/effect/click2.ogg differ diff --git a/sources/media/audio/effect/click3.ogg b/sources/media/audio/effect/click3.ogg new file mode 100644 index 0000000..d0de84b Binary files /dev/null and b/sources/media/audio/effect/click3.ogg differ diff --git a/sources/media/audio/effect/click4.ogg b/sources/media/audio/effect/click4.ogg new file mode 100644 index 0000000..19669ae Binary files /dev/null and b/sources/media/audio/effect/click4.ogg differ diff --git a/sources/media/audio/effect/denied.ogg b/sources/media/audio/effect/denied.ogg new file mode 100644 index 0000000..00c1a17 Binary files /dev/null and b/sources/media/audio/effect/denied.ogg differ diff --git a/sources/media/audio/effect/done.ogg b/sources/media/audio/effect/done.ogg new file mode 100644 index 0000000..d116c94 Binary files /dev/null and b/sources/media/audio/effect/done.ogg differ diff --git a/sources/media/audio/effect/flip.ogg b/sources/media/audio/effect/flip.ogg new file mode 100644 index 0000000..ddd33ae Binary files /dev/null and b/sources/media/audio/effect/flip.ogg differ diff --git a/sources/media/clove/10.svg b/sources/media/clove/10.svg new file mode 100644 index 0000000..4eee6b7 --- /dev/null +++ b/sources/media/clove/10.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/sources/media/clove/11.svg b/sources/media/clove/11.svg new file mode 100644 index 0000000..572d55d --- /dev/null +++ b/sources/media/clove/11.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/media/clove/13.svg b/sources/media/clove/13.svg new file mode 100644 index 0000000..f5359bb --- /dev/null +++ b/sources/media/clove/13.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/media/clove/15.svg b/sources/media/clove/15.svg new file mode 100644 index 0000000..c333ba2 --- /dev/null +++ b/sources/media/clove/15.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/media/clove/17.svg b/sources/media/clove/17.svg new file mode 100644 index 0000000..fd44480 --- /dev/null +++ b/sources/media/clove/17.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/media/clove/2.svg b/sources/media/clove/2.svg new file mode 100644 index 0000000..924050c --- /dev/null +++ b/sources/media/clove/2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/sources/media/clove/3.svg b/sources/media/clove/3.svg new file mode 100644 index 0000000..b7f123a --- /dev/null +++ b/sources/media/clove/3.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/sources/media/clove/4.svg b/sources/media/clove/4.svg new file mode 100644 index 0000000..c9ae445 --- /dev/null +++ b/sources/media/clove/4.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/sources/media/clove/5.svg b/sources/media/clove/5.svg new file mode 100644 index 0000000..245f266 --- /dev/null +++ b/sources/media/clove/5.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/sources/media/clove/6.svg b/sources/media/clove/6.svg new file mode 100644 index 0000000..60a0c64 --- /dev/null +++ b/sources/media/clove/6.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sources/media/clove/7.svg b/sources/media/clove/7.svg new file mode 100644 index 0000000..dd0518e --- /dev/null +++ b/sources/media/clove/7.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/sources/media/clove/8.svg b/sources/media/clove/8.svg new file mode 100644 index 0000000..5cdd9be --- /dev/null +++ b/sources/media/clove/8.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/sources/media/clove/9.svg b/sources/media/clove/9.svg new file mode 100644 index 0000000..5521485 --- /dev/null +++ b/sources/media/clove/9.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/sources/media/diamond/10.svg b/sources/media/diamond/10.svg new file mode 100644 index 0000000..8bd13b5 --- /dev/null +++ b/sources/media/diamond/10.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/sources/media/diamond/11.svg b/sources/media/diamond/11.svg new file mode 100644 index 0000000..b3ad935 --- /dev/null +++ b/sources/media/diamond/11.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/media/diamond/2.svg b/sources/media/diamond/2.svg new file mode 100644 index 0000000..4c3450b --- /dev/null +++ b/sources/media/diamond/2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/sources/media/diamond/3.svg b/sources/media/diamond/3.svg new file mode 100644 index 0000000..d3e6b3d --- /dev/null +++ b/sources/media/diamond/3.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/sources/media/diamond/4.svg b/sources/media/diamond/4.svg new file mode 100644 index 0000000..43a6e6d --- /dev/null +++ b/sources/media/diamond/4.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/sources/media/diamond/5.svg b/sources/media/diamond/5.svg new file mode 100644 index 0000000..178db49 --- /dev/null +++ b/sources/media/diamond/5.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/sources/media/diamond/6.svg b/sources/media/diamond/6.svg new file mode 100644 index 0000000..5115652 --- /dev/null +++ b/sources/media/diamond/6.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/sources/media/diamond/7.svg b/sources/media/diamond/7.svg new file mode 100644 index 0000000..4c8f6f9 --- /dev/null +++ b/sources/media/diamond/7.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/sources/media/diamond/8.svg b/sources/media/diamond/8.svg new file mode 100644 index 0000000..ff8b120 --- /dev/null +++ b/sources/media/diamond/8.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/sources/media/diamond/9.svg b/sources/media/diamond/9.svg new file mode 100644 index 0000000..f152698 --- /dev/null +++ b/sources/media/diamond/9.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/sources/media/fonts/input_mono_medium.ttf b/sources/media/fonts/input_mono_medium.ttf new file mode 100644 index 0000000..0d488bf Binary files /dev/null and b/sources/media/fonts/input_mono_medium.ttf differ diff --git a/sources/media/fonts/input_mono_regular.ttf b/sources/media/fonts/input_mono_regular.ttf new file mode 100644 index 0000000..c19c287 Binary files /dev/null and b/sources/media/fonts/input_mono_regular.ttf differ diff --git a/sources/media/heart/10.svg b/sources/media/heart/10.svg new file mode 100644 index 0000000..a92edbf --- /dev/null +++ b/sources/media/heart/10.svg @@ -0,0 +1,3 @@ + + + diff --git a/sources/media/heart/11.svg b/sources/media/heart/11.svg new file mode 100644 index 0000000..1f9c63c --- /dev/null +++ b/sources/media/heart/11.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/media/heart/2.svg b/sources/media/heart/2.svg new file mode 100644 index 0000000..8251e06 --- /dev/null +++ b/sources/media/heart/2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/sources/media/heart/3.svg b/sources/media/heart/3.svg new file mode 100644 index 0000000..94b07d4 --- /dev/null +++ b/sources/media/heart/3.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/sources/media/heart/4.svg b/sources/media/heart/4.svg new file mode 100644 index 0000000..4630cd4 --- /dev/null +++ b/sources/media/heart/4.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/sources/media/heart/5.svg b/sources/media/heart/5.svg new file mode 100644 index 0000000..6cea6af --- /dev/null +++ b/sources/media/heart/5.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/sources/media/heart/6.svg b/sources/media/heart/6.svg new file mode 100644 index 0000000..ee09a6b --- /dev/null +++ b/sources/media/heart/6.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sources/media/heart/7.svg b/sources/media/heart/7.svg new file mode 100644 index 0000000..21e7219 --- /dev/null +++ b/sources/media/heart/7.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/sources/media/heart/8.svg b/sources/media/heart/8.svg new file mode 100644 index 0000000..a9b8579 --- /dev/null +++ b/sources/media/heart/8.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/sources/media/heart/9.svg b/sources/media/heart/9.svg new file mode 100644 index 0000000..585af2e --- /dev/null +++ b/sources/media/heart/9.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/sources/media/icon.finder b/sources/media/icon.finder new file mode 100644 index 0000000..5bc12e7 --- /dev/null +++ b/sources/media/icon.finder @@ -0,0 +1,22 @@ +How to use this icon: + +Step 1: Copy the icon to the clipboard +a) Click on this file from the Finder +b) Choose 'Get Info' from the 'File' menu. +c) In the info window that pops up, click on the icon +d) Choose 'Copy' from the 'Edit' menu. +e) Close the info window + +Step 2: Paste the icon to the desired item +a) Go to the item in the Finder that you want a custom icon +b) Click the item (file, folder, disk, etc) +b) Choose 'Get Info' from the 'File' menu. +c) In the info window that pops up, click on the icon +d) Choose 'Paste' from the 'Edit' menu. +e) Close the info window + +Step 3: +Enjoy your newly customized icon! + +For more thorough directions, see Apple's website at: +http://www.apple.com/support/mac101/customize/6/ diff --git a/sources/media/icon.svg b/sources/media/icon.svg new file mode 100644 index 0000000..d888d0e --- /dev/null +++ b/sources/media/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sources/media/icon180x180.png b/sources/media/icon180x180.png new file mode 100644 index 0000000..80fdc22 Binary files /dev/null and b/sources/media/icon180x180.png differ diff --git a/sources/media/joker/21.svg b/sources/media/joker/21.svg new file mode 100644 index 0000000..4613569 --- /dev/null +++ b/sources/media/joker/21.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/sources/media/spade/10.svg b/sources/media/spade/10.svg new file mode 100644 index 0000000..96e30de --- /dev/null +++ b/sources/media/spade/10.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/sources/media/spade/11.svg b/sources/media/spade/11.svg new file mode 100644 index 0000000..075b9f9 --- /dev/null +++ b/sources/media/spade/11.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/media/spade/13.svg b/sources/media/spade/13.svg new file mode 100644 index 0000000..c18853f --- /dev/null +++ b/sources/media/spade/13.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/media/spade/15.svg b/sources/media/spade/15.svg new file mode 100644 index 0000000..195dfde --- /dev/null +++ b/sources/media/spade/15.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/media/spade/17.svg b/sources/media/spade/17.svg new file mode 100644 index 0000000..de40de6 --- /dev/null +++ b/sources/media/spade/17.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/media/spade/2.svg b/sources/media/spade/2.svg new file mode 100644 index 0000000..a251e86 --- /dev/null +++ b/sources/media/spade/2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/sources/media/spade/3.svg b/sources/media/spade/3.svg new file mode 100644 index 0000000..3dff615 --- /dev/null +++ b/sources/media/spade/3.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/sources/media/spade/4.svg b/sources/media/spade/4.svg new file mode 100644 index 0000000..0c95fad --- /dev/null +++ b/sources/media/spade/4.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/sources/media/spade/5.svg b/sources/media/spade/5.svg new file mode 100644 index 0000000..9b3b57d --- /dev/null +++ b/sources/media/spade/5.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/sources/media/spade/6.svg b/sources/media/spade/6.svg new file mode 100644 index 0000000..e0404b3 --- /dev/null +++ b/sources/media/spade/6.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sources/media/spade/7.svg b/sources/media/spade/7.svg new file mode 100644 index 0000000..7a9f1bf --- /dev/null +++ b/sources/media/spade/7.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/sources/media/spade/8.svg b/sources/media/spade/8.svg new file mode 100644 index 0000000..1b68e9c --- /dev/null +++ b/sources/media/spade/8.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/sources/media/spade/9.svg b/sources/media/spade/9.svg new file mode 100644 index 0000000..5adf324 --- /dev/null +++ b/sources/media/spade/9.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/sources/scripts/board.js b/sources/scripts/board.js new file mode 100644 index 0000000..c00416a --- /dev/null +++ b/sources/scripts/board.js @@ -0,0 +1,122 @@ +'use strict' + +function Board (element) { + this.element = element + this.room = [] + + this.enter_room = function (starting_hand = null) { + this.remove_cards() + + if (donsol.deck.cards.length > 0) { + this.add_card(0, donsol.deck.draw_card(starting_hand ? DIAMOND : null)) + setTimeout(() => { + this.room[0].element.style.opacity = 1 + this.room[0].element.style.top = 0 + donsol.speaker.play_effect('click2') + }, 100) + } + if (donsol.deck.cards.length > 0) { + this.add_card(1, donsol.deck.draw_card(starting_hand ? CLOVE : null)) + setTimeout(() => { + this.room[1].element.style.opacity = 1 + this.room[1].element.style.top = 0 + donsol.speaker.play_effect('click2') + }, 150) + } + if (donsol.deck.cards.length > 0) { + this.add_card(2, donsol.deck.draw_card(starting_hand ? HEART : null)) + setTimeout(() => { + this.room[2].element.style.opacity = 1 + this.room[2].element.style.top = 0 + donsol.speaker.play_effect('click2') + }, 200) + } + if (donsol.deck.cards.length > 0) { + this.add_card(3, donsol.deck.draw_card(starting_hand ? SPADE : null)) + setTimeout(() => { + this.room[3].element.style.opacity = 1 + this.room[3].element.style.top = 0 + donsol.speaker.play_effect('click2') + }, 250) + } + + donsol.player.update() + this.update() + } + + this.add_card = function (index, card) { + this.element.appendChild(card.install()) + this.room.push(card) + } + + this.remove_cards = function () { + this.room = [] + this.element.innerHTML = '' + } + + this.return_cards = function () { + if (!this.room[0].is_flipped) { donsol.deck.return_card(this.room[0]) } + if (!this.room[1].is_flipped) { donsol.deck.return_card(this.room[1]) } + if (!this.room[2].is_flipped) { donsol.deck.return_card(this.room[2]) } + if (!this.room[3].is_flipped) { donsol.deck.return_card(this.room[3]) } + } + + this.update = function () { + // Don't draw if the player is dead + if (donsol.player.health.value < 1) { + return + } + + if (donsol.player.experience.value === donsol.player.experience.limit) { + this.dungeon_complete() + return + } + if (this.room[0].is_flipped && this.room[1].is_flipped && this.room[2].is_flipped && this.room[3].is_flipped) { + setTimeout(function () { donsol.board.is_complete() }, 250) + } + } + + // Checks + + this.is_complete = function () { + donsol.player.has_escaped = false + this.enter_room() + } + + this.is_started = function () { + return this.cards_flipped().length > 0 + } + + this.has_monsters = function () { + return this.cards_monsters().length > 0 + } + + this.cards_flipped = function () { + const a = [] + if (this.room[0] && this.room[0].is_flipped) { a.push(this.room[0]) } + if (this.room[1] && this.room[1].is_flipped) { a.push(this.room[1]) } + if (this.room[2] && this.room[2].is_flipped) { a.push(this.room[2]) } + if (this.room[3] && this.room[3].is_flipped) { a.push(this.room[3]) } + return a + } + + this.cards_monsters = function () { + const a = [] + if (this.room[0] && this.room[0].constructor.name == 'Card_Monster' && this.room[0].is_flipped === false) { a.push(this.room[0]) } + if (this.room[1] && this.room[1].constructor.name == 'Card_Monster' && this.room[1].is_flipped === false) { a.push(this.room[1]) } + if (this.room[2] && this.room[2].constructor.name == 'Card_Monster' && this.room[2].is_flipped === false) { a.push(this.room[2]) } + if (this.room[3] && this.room[3].constructor.name == 'Card_Monster' && this.room[3].is_flipped === false) { a.push(this.room[3]) } + return a + } + + this.dungeon_complete = function () { + donsol.is_complete = true + donsol.player.escape_button.innerHTML = 'Restart' + donsol.player.element.setAttribute('class', 'done') + donsol.timeline.add_event('Completed dungeon!') + } + + this.dungeon_failed = function () { + + } +} diff --git a/sources/scripts/card.js b/sources/scripts/card.js new file mode 100644 index 0000000..a2d325e --- /dev/null +++ b/sources/scripts/card.js @@ -0,0 +1,69 @@ +'use strict' + +function Card (sym, value, type, name = 'Unknown') { + this.symbol = sym + this.value = value + this.type = type + this.name = name + + this.element = null + this.is_flipped = false + + this.install = function () { + const e = document.createElement('card') + e.setAttribute('class', this.type + ' card_' + this.value) + + // Face + const face = document.createElement('div') + face.setAttribute('class', 'face') + e.appendChild(face) + + // Value + const value = document.createElement('span') + value.setAttribute('class', 'value') + value.innerHTML = this.symbol + face.appendChild(value) + + const graphic = document.createElement('div') + graphic.className = 'graphic' + graphic.innerHTML = require('fs').readFileSync(`${__dirname}/media/${this.type}/${this.value}.svg`) + face.appendChild(graphic) + + // Name + const name_element = document.createElement('span') + name_element.setAttribute('class', 'name') + name_element.innerHTML = this.name + ' ' + this.value + face.appendChild(name_element) + + // Icon + face.appendChild(new Icon(this.type).install()) + + addClickHandler(e, this, this.value) + + this.element = e + + return e + } + + function addClickHandler (elem, object) { + elem.addEventListener('click', function (e) { object.touch() }, false) + } + + this.touch = function () { + console.log('??') + } + + this.flip = function () { + donsol.speaker.play_effect('flip') + + this.is_flipped = true + donsol.player.experience.value += 1 + donsol.player.experience.update() + + this.element.style.opacity = '0' + this.element.style.top = '-5px' + donsol.speaker.play_effect('click2') + + donsol.player.update() + } +} diff --git a/sources/scripts/card.monster.js b/sources/scripts/card.monster.js new file mode 100644 index 0000000..2644db7 --- /dev/null +++ b/sources/scripts/card.monster.js @@ -0,0 +1,13 @@ +'use strict' + +function Card_Monster (sym, value, type, name = 'Unknown') { + Card.call(this, sym, value, type, name) + + this.touch = function () { + if (this.is_flipped) { console.log('Card is already flipped'); return } + if (donsol.player.health.value < 1) { console.log('Player is dead'); return } + this.flip() + donsol.player.attack(this) + donsol.board.update() + } +} diff --git a/sources/scripts/card.potion.js b/sources/scripts/card.potion.js new file mode 100644 index 0000000..aa3d600 --- /dev/null +++ b/sources/scripts/card.potion.js @@ -0,0 +1,13 @@ +'use strict' + +function Card_Potion (sym, value, type, name = 'Unknown') { + Card.call(this, sym, value, type, name) + + this.touch = function () { + if (this.is_flipped) { console.log('Card is already flipped'); return } + if (donsol.player.health.value < 1) { console.log('Player is dead'); return } + this.flip() + donsol.player.drink_potion(this.value) + donsol.board.update() + } +} diff --git a/sources/scripts/card.shield.js b/sources/scripts/card.shield.js new file mode 100644 index 0000000..19cd345 --- /dev/null +++ b/sources/scripts/card.shield.js @@ -0,0 +1,13 @@ +'use strict' + +function Card_Shield (sym, value, type, name = 'Unknown') { + Card.call(this, sym, value, type, name) + + this.touch = function () { + if (this.is_flipped == true) { console.log('Card is already flipped'); return } + if (donsol.player.health.value < 1) { console.log('Player is dead'); return } + this.flip() + donsol.player.equip_shield(this.value) + donsol.board.update() + } +} diff --git a/sources/scripts/deck.js b/sources/scripts/deck.js new file mode 100644 index 0000000..acf974e --- /dev/null +++ b/sources/scripts/deck.js @@ -0,0 +1,103 @@ +'use strict' + +function Deck () { + this.cards = [ + new Card_Potion('A', 11, HEART, 'White Mage'), + new Card_Potion('2', 2, HEART, 'Small Potion'), + new Card_Potion('3', 3, HEART, 'Small Potion'), + new Card_Potion('4', 4, HEART, 'Medium Potion'), + new Card_Potion('5', 5, HEART, 'Medium Potion'), + new Card_Potion('6', 6, HEART, 'Medium Potion'), + new Card_Potion('7', 7, HEART, 'Medium Potion'), + new Card_Potion('8', 8, HEART, 'Medium Potion'), + new Card_Potion('9', 9, HEART, 'Large Potion'), + new Card_Potion('10', 10, HEART, 'Large Potion'), + new Card_Potion('V', 11, HEART, 'White Mage'), + new Card_Potion('Q', 11, HEART, 'White Mage'), + new Card_Potion('K', 11, HEART, 'White Mage'), + new Card_Shield('A', 11, DIAMOND, 'Red Mage'), + new Card_Shield('2', 2, DIAMOND, 'Buckler'), + new Card_Shield('3', 3, DIAMOND, 'Buckler'), + new Card_Shield('4', 4, DIAMOND, 'Shield'), + new Card_Shield('5', 5, DIAMOND, 'Shield'), + new Card_Shield('6', 6, DIAMOND, 'Shield'), + new Card_Shield('7', 7, DIAMOND, 'Shield'), + new Card_Shield('8', 8, DIAMOND, 'Shield'), + new Card_Shield('9', 9, DIAMOND, 'Large Shield'), + new Card_Shield('10', 10, DIAMOND, 'Large Shield'), + new Card_Shield('V', 11, DIAMOND, 'Red Mage'), + new Card_Shield('Q', 11, DIAMOND, 'Red Mage'), + new Card_Shield('K', 11, DIAMOND, 'Red Mage'), + new Card_Monster('A', 17, CLOVE, 'Empress'), + new Card_Monster('2', 2, CLOVE, 'Rat'), + new Card_Monster('3', 3, CLOVE, 'Bat'), + new Card_Monster('4', 4, CLOVE, 'Imp'), + new Card_Monster('5', 5, CLOVE, 'Goblin'), + new Card_Monster('6', 6, CLOVE, 'Orc'), + new Card_Monster('7', 7, CLOVE, 'Ogre'), + new Card_Monster('8', 8, CLOVE, 'Beholder'), + new Card_Monster('9', 9, CLOVE, 'Medusa'), + new Card_Monster('10', 10, CLOVE, 'Demon'), + new Card_Monster('V', 11, CLOVE, 'Consort'), + new Card_Monster('Q', 13, CLOVE, 'Queen'), + new Card_Monster('K', 15, CLOVE, 'Regnant'), + new Card_Monster('A', 17, SPADE, 'Empress'), + new Card_Monster('2', 2, SPADE, 'Slime'), + new Card_Monster('3', 3, SPADE, 'Tunneler'), + new Card_Monster('4', 4, SPADE, 'Fiend'), + new Card_Monster('5', 5, SPADE, 'Drake'), + new Card_Monster('6', 6, SPADE, 'Specter'), + new Card_Monster('7', 7, SPADE, 'Ghost'), + new Card_Monster('8', 8, SPADE, 'Elemental'), + new Card_Monster('9', 9, SPADE, 'Witch'), + new Card_Monster('10', 10, SPADE, 'Familiar'), + new Card_Monster('V', 11, SPADE, 'Consort'), + new Card_Monster('Q', 13, SPADE, 'Queen'), + new Card_Monster('K', 15, SPADE, 'Regnant'), + new Card_Monster('J', 21, JOKER, 'First Donsol'), + new Card_Monster('J', 21, JOKER, 'Second Donsol') + ] + + let draw_pile = [] + + this.start = function () { + draw_pile = this.cards + donsol.timeline.add_event(`Entered Donsol, at ${donsol.get_difficulty()} difficulty.`) + } + + this.shuffle = function () { + draw_pile = shuffle(this.cards) + donsol.timeline.add_event(`Entered Donsol, at ${donsol.get_difficulty()} difficulty.`) + } + + this.draw_card = function (type) { + let i = 0 + switch (type) { + case HEART: + i = Math.floor((Math.random() * 10) + 0); break + case DIAMOND: + i = Math.floor((Math.random() * 10) + 13); break + case CLOVE: + i = Math.floor((Math.random() * 10) + 25); break + case SPADE: + i = Math.floor((Math.random() * 10) + 36); break + } + + return draw_pile.splice(i, 1)[0] + } + + this.return_card = function (card) { + draw_pile.push(card) + draw_pile = shuffle(draw_pile) + } + + function shuffle (array) { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)) + const temp = array[i] + array[i] = array[j] + array[j] = temp + } + return array + } +} diff --git a/sources/scripts/donsol.js b/sources/scripts/donsol.js new file mode 100644 index 0000000..2553a1a --- /dev/null +++ b/sources/scripts/donsol.js @@ -0,0 +1,91 @@ +'use strict' + +const HEART = 'heart' +const DIAMOND = 'diamond' +const CLOVE = 'clove' +const SPADE = 'spade' +const JOKER = 'joker' + +function Donsol () { + const defaultTheme = { + background: '#000000', + f_high: '#000000', + f_med: '#a93232', + f_low: '#aaaaaa', + f_inv: '#ffffff', + b_high: '#ffffff', + b_med: '#cccccc', + b_low: '#333333', + b_inv: '#a93232' + } + + this.theme = new Theme(defaultTheme) + + this.deck = new Deck() + this.board = new Board() + this.player = new Player() + this.timeline = new Timeline() + this.controller = new Controller() + this.speaker = new Speaker() + this.walkthrough = new Walkthrough() + + this.is_complete = false + this.difficulty = 1 + + this.install = function (host = document.body) { + this.theme.install(host) + } + + this.start = function () { + donsol.board.element = document.getElementById('board') + donsol.player.element = document.getElementById('player') + + this.theme.start() + this.deck.start() + this.player.install() + donsol.timeline.install(donsol.player.element) + this.player.start() + + this.board.enter_room(true) + donsol.deck.shuffle() + + this.update() + } + + this.new_game = function () { + this.deck = new Deck() + this.deck.start() + + this.player.start() + this.board.enter_room(true) + donsol.deck.shuffle() + + this.update() + } + + this.toggle_difficulty = function () { + this.difficulty = this.difficulty < 3 ? this.difficulty + 1 : 0 + donsol.new_game() + } + + this.set_difficulty = function (id) { + this.difficulty = id + donsol.new_game() + } + + this.get_difficulty = function () { + return this.difficulty == 3 ? 'Expert' : this.difficulty == 2 ? 'Hard' : this.difficulty == 1 ? 'Normal' : 'Easy' + } + + this.update = function () { + console.log('Difficulty', this.get_difficulty()) + } + + this.skip = function () { + if (donsol.player.experience.value < 1) { + donsol.new_game() + } else { + donsol.player.escape_room() + } + } +} diff --git a/sources/scripts/gage.health.js b/sources/scripts/gage.health.js new file mode 100644 index 0000000..6d19008 --- /dev/null +++ b/sources/scripts/gage.health.js @@ -0,0 +1,15 @@ +'use strict' + +function Gage_Health (name, limit, color) { + Gage.call(this, name, limit, color) + + this.update = function () { + this.progress.update(this.value, this.limit) + + if (donsol.player.can_drink === false) { + this.value_element.innerHTML = `${this.value} HP` + } else { + this.value_element.innerHTML = `${this.value} HP` + } + } +} diff --git a/sources/scripts/gage.js b/sources/scripts/gage.js new file mode 100644 index 0000000..9303f23 --- /dev/null +++ b/sources/scripts/gage.js @@ -0,0 +1,66 @@ +'use strict' + +function Gage (name, limit, color) { + this.name = name + this.color = color + this.limit = limit + this.value = limit + this.value_element = null + this.event_element = null + this.element = document.createElement('div') + this.progress = new Progress(15, color) + + this.show_limit = true + this.units = '' + + this.start = function () { + this.install() + } + + this.install = function () { + this.element.setAttribute('class', 'gage ' + this.name.toLowerCase()) + + this.value_element = document.createElement('span') + this.value_element.setAttribute('class', 'value') + this.value_element.innerHTML = this.value + '(' + this.limit + ')' + this.element.appendChild(this.value_element) + + this.event_element = document.createElement('span') + this.event_element.setAttribute('class', 'event') + this.element.appendChild(this.event_element) + + this.element.appendChild(this.progress.install()) + + return this.element + } + + this.update = function (value) { + this.value = typeof value === 'number' ? value : this.value + if (this.value > this.limit) { this.value = this.limit } + if (this.value < 0) { this.value = 0 } + + this.progress.update(this.value, this.limit) + + if (this.name == 'Shield' && this.value == 0) { + this.value_element.innerHTML = "0DP" + } else if (this.name == 'Shield' && this.limit == 25) { + this.value_element.innerHTML = this.value + "DP" + } else { + this.value_element.innerHTML = this.show_limit ? this.value + ' < ' + this.limit + "" + this.units + '' : this.value + " " + this.units + '' + } + } + + this.add_event = function (value) { + this.event_element.innerHTML = "" + value + '' + this.event_element.style.marginTop = '5px' + this.event_element.style.opacity = '0' + setTimeout(() => { + this.event_element.style.marginTop = '0px' + this.event_element.style.opacity = 1 + }, 250) + } + + this.clear_event = function () { + this.event_element.innerHTML = '' + } +} diff --git a/sources/scripts/gage.progress.js b/sources/scripts/gage.progress.js new file mode 100644 index 0000000..a73c734 --- /dev/null +++ b/sources/scripts/gage.progress.js @@ -0,0 +1,29 @@ +'use strict' + +function Progress (radius = 15) { + this.wrapper = null + this.progress_bar = null + + this.install = function () { + this.wrapper = document.createElement('div') + this.wrapper.setAttribute('class', 'progress') + + this.progress_bar = document.createElement('div') + this.progress_bar.setAttribute('class', 'bar') + + this.wrapper.appendChild(this.progress_bar) + + return this.wrapper + } + + this.update = function (value, limit = 0) { + if (limit === 0) { value = 0; limit = 1 } + const min = 0 + const max = 130 + const pixels = Math.floor(((value / limit) * max) + min) + const ratio = (value / limit) + const perc = ratio * 100 + + this.progress_bar.style.width = `${perc}%` + } +} diff --git a/sources/scripts/gage.shield.js b/sources/scripts/gage.shield.js new file mode 100644 index 0000000..ffff279 --- /dev/null +++ b/sources/scripts/gage.shield.js @@ -0,0 +1,25 @@ +'use strict' + +function Gage_Shield (name, limit, color) { + Gage.call(this, name, limit, color) + + this.break_limit = null + + this.update = function () { + if (this.is_damaged() === true) { + this.value_element.innerHTML = `${this.break_limit - 1}/${this.value} DP` + this.progress.update(this.value < this.break_limit ? this.value : this.break_limit - 1, 11) + } else if (this.value == 0) { + this.value_element.innerHTML = "0 DP" + this.progress.update(0, 11) + } else { + this.value_element.innerHTML = '' + this.value + " DP" + this.progress.update(this.value, 11) + } + } + + this.is_damaged = function () { + if (this.break_limit === null) { return false } + return true + } +} diff --git a/sources/scripts/icon.js b/sources/scripts/icon.js new file mode 100644 index 0000000..415edea --- /dev/null +++ b/sources/scripts/icon.js @@ -0,0 +1,105 @@ +'use strict' + +function Icon (type) { + this.type = type + + this.install = function () { + switch (this.type) { + case HEART: + return this.heart() + case DIAMOND: + return this.diamond() + case CLOVE: + return this.clove() + case SPADE: + return this.spade() + case JOKER: + return this.joker() + } + } + + this.heart = function () { + const e = document.createElementNS('http://www.w3.org/2000/svg', 'svg') + e.setAttribute('class', 'icon') + + const s = document.createElementNS('http://www.w3.org/2000/svg', 'path') + s.setAttribute('d', 'M0,15 a15,15 0 0,1 30,0 l-15,15 l-15,-15') + s.setAttribute('class', 'fill_red') + + e.appendChild(s) + return e + } + + this.diamond = function () { + const e = document.createElementNS('http://www.w3.org/2000/svg', 'svg') + e.setAttribute('class', 'icon') + + const s = document.createElementNS('http://www.w3.org/2000/svg', 'path') + s.setAttribute('d', 'M15 0 L 30 15 L 15 30 L 0 15') + s.setAttribute('class', 'fill_red') + + e.appendChild(s) + return e + } + + this.clove = function () { + const e = document.createElementNS('http://www.w3.org/2000/svg', 'svg') + e.setAttribute('class', 'icon') + + const s = document.createElementNS('http://www.w3.org/2000/svg', 'circle') + s.setAttribute('cx', '15px') + s.setAttribute('cy', '6px') + s.setAttribute('r', '5px') + s.setAttribute('class', 'fill_black') + e.appendChild(s) + + const s2 = document.createElementNS('http://www.w3.org/2000/svg', 'circle') + s2.setAttribute('cx', '24px') + s2.setAttribute('cy', '15px') + s2.setAttribute('r', '5px') + s2.setAttribute('class', 'fill_black') + e.appendChild(s2) + + const s3 = document.createElementNS('http://www.w3.org/2000/svg', 'circle') + s3.setAttribute('cx', '6px') + s3.setAttribute('cy', '15px') + s3.setAttribute('r', '5px') + s3.setAttribute('class', 'fill_black') + e.appendChild(s3) + + const s4 = document.createElementNS('http://www.w3.org/2000/svg', 'circle') + s4.setAttribute('cx', '15px') + s4.setAttribute('cy', '24px') + s4.setAttribute('r', '5px') + s4.setAttribute('class', 'fill_black') + e.appendChild(s4) + + return e + } + + this.spade = function () { + const e = document.createElementNS('http://www.w3.org/2000/svg', 'svg') + e.setAttribute('class', 'icon') + + const s = document.createElementNS('http://www.w3.org/2000/svg', 'path') + s.setAttribute('d', 'M15,0 L0,15 a15,15 0 0,1 15,15 a15,15 0 0,1 15,-15') + s.setAttribute('class', 'fill_black') + + e.appendChild(s) + return e + } + + this.joker = function () { + const e = document.createElementNS('http://www.w3.org/2000/svg', 'svg') + e.setAttribute('class', 'icon') + + const s = document.createElementNS('http://www.w3.org/2000/svg', 'circle') + s.setAttribute('cx', '15px') + s.setAttribute('cy', '15px') + s.setAttribute('r', '15px') + s.setAttribute('class', 'fill_black') + e.appendChild(s) + + return e + } +} diff --git a/sources/scripts/lib/controller.js b/sources/scripts/lib/controller.js new file mode 100644 index 0000000..365c368 --- /dev/null +++ b/sources/scripts/lib/controller.js @@ -0,0 +1,185 @@ +'use strict' + +function Controller () { + this.menu = { default: {} } + this.mode = 'default' + + this.app = require('electron').remote.app + + this.start = function () { + } + + this.add = function (mode, cat, label, fn, accelerator) { + if (!this.menu[mode]) { this.menu[mode] = {} } + if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} } + this.menu[mode][cat][label] = { fn: fn, accelerator: accelerator } + console.log(`${mode}/${cat}/${label} <${accelerator}>`) + } + + this.add_role = function (mode, cat, label) { + if (!this.menu[mode]) { this.menu[mode] = {} } + if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} } + this.menu[mode][cat][label] = { role: label } + } + + this.set = function (mode = 'default') { + this.mode = mode + this.commit() + } + + this.format = function () { + const f = [] + const m = this.menu[this.mode] + for (const cat in m) { + const submenu = [] + for (name in m[cat]) { + const option = m[cat][name] + if (option.role) { + submenu.push({ role: option.role }) + } else { + submenu.push({ label: name, accelerator: option.accelerator, click: option.fn }) + } + } + f.push({ label: cat, submenu: submenu }) + } + return f + } + + this.commit = function () { + this.app.inject_menu(this.format()) + } + + this.docs = function () { + console.log('Generating docs..') + const svg = this.generate_svg(this.format()) + const txt = this.documentation(this.format()) + dialog.showSaveDialog((fileName) => { + if (fileName === undefined) { return } + fileName = fileName.substr(-4, 4) != '.svg' ? fileName + '.svg' : fileName + fs.writeFile(fileName, svg) + fs.writeFile(fileName.replace('.svg', '.md'), txt) + }) + } + + this.generate_svg = function (m) { + let svg_html = '' + + for (id in this.layout) { + const key = this.layout[id] + const acc = this.accelerator_for_key(key.name, m) + svg_html += `` + svg_html += `` + svg_html += `${key.name.toUpperCase()}` + svg_html += acc && acc.basic ? `${acc.basic}` : '' + svg_html += acc && acc.ctrl ? `${acc.ctrl}` : '' + } + return `${svg_html}` + } + + this.documentation = function () { + let txt = '' + + txt += this.documentation_for_mode('default', this.menu.default) + + for (name in this.menu) { + if (name == 'default') { continue } + txt += this.documentation_for_mode(name, this.menu[name]) + } + return txt + } + + this.documentation_for_mode = function (name, mode) { + let txt = `## ${name} Mode\n\n` + + for (id in mode) { + if (id == '*') { continue } + txt += `### ${id}\n` + for (name in mode[id]) { + const option = mode[id][name] + txt += `- ${name}: \`${option.accelerator}\`\n` + } + txt += '\n' + } + + return txt + '\n' + } + + this.accelerator_for_key = function (key, menu) { + const acc = { basic: null, ctrl: null } + for (cat in menu) { + const options = menu[cat] + for (id in options.submenu) { + const option = options.submenu[id]; if (option.role) { continue } + acc.basic = (option.accelerator.toLowerCase() == key.toLowerCase()) ? option.label.toUpperCase().replace('TOGGLE ', '').substr(0, 8).trim() : acc.basic + acc.ctrl = (option.accelerator.toLowerCase() == ('CmdOrCtrl+' + key).toLowerCase()) ? option.label.toUpperCase().replace('TOGGLE ', '').substr(0, 8).trim() : acc.ctrl + } + } + return acc + } + + this.layout = [ + { x: 0, y: 0, width: 60, height: 60, name: 'esc' }, + { x: 60, y: 0, width: 60, height: 60, name: '1' }, + { x: 120, y: 0, width: 60, height: 60, name: '2' }, + { x: 180, y: 0, width: 60, height: 60, name: '3' }, + { x: 240, y: 0, width: 60, height: 60, name: '4' }, + { x: 300, y: 0, width: 60, height: 60, name: '5' }, + { x: 360, y: 0, width: 60, height: 60, name: '6' }, + { x: 420, y: 0, width: 60, height: 60, name: '7' }, + { x: 480, y: 0, width: 60, height: 60, name: '8' }, + { x: 540, y: 0, width: 60, height: 60, name: '9' }, + { x: 600, y: 0, width: 60, height: 60, name: '0' }, + { x: 660, y: 0, width: 60, height: 60, name: '-' }, + { x: 720, y: 0, width: 60, height: 60, name: 'plus' }, + { x: 780, y: 0, width: 120, height: 60, name: 'backspace' }, + { x: 0, y: 60, width: 90, height: 60, name: 'tab' }, + { x: 90, y: 60, width: 60, height: 60, name: 'q' }, + { x: 150, y: 60, width: 60, height: 60, name: 'w' }, + { x: 210, y: 60, width: 60, height: 60, name: 'e' }, + { x: 270, y: 60, width: 60, height: 60, name: 'r' }, + { x: 330, y: 60, width: 60, height: 60, name: 't' }, + { x: 390, y: 60, width: 60, height: 60, name: 'y' }, + { x: 450, y: 60, width: 60, height: 60, name: 'u' }, + { x: 510, y: 60, width: 60, height: 60, name: 'i' }, + { x: 570, y: 60, width: 60, height: 60, name: 'o' }, + { x: 630, y: 60, width: 60, height: 60, name: 'p' }, + { x: 690, y: 60, width: 60, height: 60, name: '[' }, + { x: 750, y: 60, width: 60, height: 60, name: ']' }, + { x: 810, y: 60, width: 90, height: 60, name: '|' }, + { x: 0, y: 120, width: 105, height: 60, name: 'caps' }, + { x: 105, y: 120, width: 60, height: 60, name: 'a' }, + { x: 165, y: 120, width: 60, height: 60, name: 's' }, + { x: 225, y: 120, width: 60, height: 60, name: 'd' }, + { x: 285, y: 120, width: 60, height: 60, name: 'f' }, + { x: 345, y: 120, width: 60, height: 60, name: 'g' }, + { x: 405, y: 120, width: 60, height: 60, name: 'h' }, + { x: 465, y: 120, width: 60, height: 60, name: 'j' }, + { x: 525, y: 120, width: 60, height: 60, name: 'k' }, + { x: 585, y: 120, width: 60, height: 60, name: 'l' }, + { x: 645, y: 120, width: 60, height: 60, name: ';' }, + { x: 705, y: 120, width: 60, height: 60, name: "'" }, + { x: 765, y: 120, width: 135, height: 60, name: 'enter' }, + { x: 0, y: 180, width: 135, height: 60, name: 'shift' }, + { x: 135, y: 180, width: 60, height: 60, name: 'z' }, + { x: 195, y: 180, width: 60, height: 60, name: 'x' }, + { x: 255, y: 180, width: 60, height: 60, name: 'c' }, + { x: 315, y: 180, width: 60, height: 60, name: 'v' }, + { x: 375, y: 180, width: 60, height: 60, name: 'b' }, + { x: 435, y: 180, width: 60, height: 60, name: 'n' }, + { x: 495, y: 180, width: 60, height: 60, name: 'm' }, + { x: 555, y: 180, width: 60, height: 60, name: ',' }, + { x: 615, y: 180, width: 60, height: 60, name: '.' }, + { x: 675, y: 180, width: 60, height: 60, name: '/' }, + { x: 735, y: 180, width: 165, height: 60, name: 'capslock' }, + { x: 0, y: 240, width: 90, height: 60, name: 'ctrl' }, + { x: 90, y: 240, width: 90, height: 60, name: 'cmd' }, + { x: 180, y: 240, width: 90, height: 60, name: 'alt' }, + { x: 270, y: 240, width: 270, height: 60, name: 'space' }, + { x: 810, y: 240, width: 90, height: 60, name: 'ctrl' }, + { x: 720, y: 240, width: 90, height: 60, name: 'pn' }, + { x: 630, y: 240, width: 90, height: 60, name: 'fn' }, + { x: 540, y: 240, width: 90, height: 60, name: 'alt' } + ] +} + +module.exports = new Controller() diff --git a/sources/scripts/lib/theme.js b/sources/scripts/lib/theme.js new file mode 100644 index 0000000..7482596 --- /dev/null +++ b/sources/scripts/lib/theme.js @@ -0,0 +1,128 @@ +'use strict' + +function Theme (_default) { + const themer = this + + this.active = _default + + this.el = document.createElement('style') + this.el.type = 'text/css' + + this.install = function (host = document.body, callback) { + console.log('Theme', 'Installing..') + host.appendChild(this.el) + this.callback = callback + } + + this.start = function () { + console.log('Theme', 'Starting..') + if (isJson(localStorage.theme)) { + const storage = JSON.parse(localStorage.theme) + if (validate(storage)) { + console.log('Theme', 'Found theme in localStorage!') + this.load(storage) + return + } + } + this.load(_default) + } + + this.load = function (data) { + const theme = parse(data) + if (!validate(theme)) { console.warn('Theme', 'Not a theme', theme); return } + console.log('Theme', `Loading theme with background ${theme.background}.`) + this.el.innerHTML = `:root { --background: ${theme.background}; --f_high: ${theme.f_high}; --f_med: ${theme.f_med}; --f_low: ${theme.f_low}; --f_inv: ${theme.f_inv}; --b_high: ${theme.b_high}; --b_med: ${theme.b_med}; --b_low: ${theme.b_low}; --b_inv: ${theme.b_inv}; }` + localStorage.setItem('theme', JSON.stringify(theme)) + this.active = theme + if (this.callback) { + this.callback() + } + } + + this.reset = function () { + this.load(_default) + } + + function parse (any) { + if (any && any.background) { return any } else if (any && any.data) { return any.data } else if (any && isJson(any)) { return JSON.parse(any) } else if (any && isHtml(any)) { return extract(any) } + return null + } + + // Drag + + this.drag = function (e) { + e.stopPropagation() + e.preventDefault() + e.dataTransfer.dropEffect = 'copy' + } + + this.drop = function (e) { + e.preventDefault() + e.stopPropagation() + const file = e.dataTransfer.files[0] + if (!file || !file.name) { console.warn('Theme', 'Unnamed file.'); return } + if (file.name.indexOf('.thm') < 0 && file.name.indexOf('.svg') < 0) { console.warn('Theme', 'Skipped, not a theme'); return } + const reader = new FileReader() + reader.onload = function (e) { + themer.load(e.target.result) + } + reader.readAsText(file) + } + + this.open = function () { + const fs = require('fs') + const { dialog, app } = require('electron').remote + const paths = dialog.showOpenDialog(app.win, { properties: ['openFile'], filters: [{ name: 'Themes', extensions: ['svg'] }] }) + if (!paths) { console.log('Nothing to load') } + fs.readFile(paths[0], 'utf8', function (err, data) { + if (err) throw err + themer.load(data) + }) + } + + window.addEventListener('dragover', this.drag) + window.addEventListener('drop', this.drop) + + // Helpers + + function validate (json) { + if (!json) { return false } + if (!json.background) { return false } + if (!json.f_high) { return false } + if (!json.f_med) { return false } + if (!json.f_low) { return false } + if (!json.f_inv) { return false } + if (!json.b_high) { return false } + if (!json.b_med) { return false } + if (!json.b_low) { return false } + if (!json.b_inv) { return false } + return true + } + + function extract (text) { + const svg = new DOMParser().parseFromString(text, 'text/xml') + try { + return { + background: svg.getElementById('background').getAttribute('fill'), + f_high: svg.getElementById('f_high').getAttribute('fill'), + f_med: svg.getElementById('f_med').getAttribute('fill'), + f_low: svg.getElementById('f_low').getAttribute('fill'), + f_inv: svg.getElementById('f_inv').getAttribute('fill'), + b_high: svg.getElementById('b_high').getAttribute('fill'), + b_med: svg.getElementById('b_med').getAttribute('fill'), + b_low: svg.getElementById('b_low').getAttribute('fill'), + b_inv: svg.getElementById('b_inv').getAttribute('fill') + } + } catch (err) { + console.warn('Theme', 'Incomplete SVG Theme', err) + } + } + + function isJson (text) { + try { JSON.parse(text); return true } catch (error) { return false } + } + + function isHtml (text) { + try { new DOMParser().parseFromString(text, 'text/xml'); return true } catch (error) { return false } + } +} diff --git a/sources/scripts/player.js b/sources/scripts/player.js new file mode 100644 index 0000000..bf7ef5e --- /dev/null +++ b/sources/scripts/player.js @@ -0,0 +1,209 @@ +'use strict' + +function Player () { + this.element = null + this.health = new Gage_Health('Health', 21, '#ff0000') + this.shield = new Gage_Shield('Shield', 0, '#72dec2') + this.experience = new Gage('Experience', 0, '#ffffff') + + this.can_drink = true + this.has_escaped = false + this.escape_button = document.createElement('a') + this.timeline_element = document.createElement('div') + + this.escape_button.addEventListener('mousedown', () => { donsol.player.escape_room() }) + + this.start = function () { + this.health.show_limit = false + this.health.units = 'HP' + this.shield.units = 'DP' + this.experience.units = 'XP' + this.experience.show_limit = false + + this.health.value = 21 + this.shield.value = 0 + this.shield.break_limit = null + this.experience.limit = 54 + this.experience.value = 0 + + this.can_drink = true + this.has_escaped = false + + this.update() + } + + this.install = function () { + this.element.appendChild(this.experience.install()) + this.element.appendChild(this.shield.install()) + this.element.appendChild(this.health.install()) + + this.escape_button.setAttribute('class', 'escape') + this.escape_button.innerHTML = 'Escape' + this.element.appendChild(this.escape_button) + this.timeline_element.setAttribute('class', 'timeline') + this.timeline_element.innerHTML = '' + this.update() + } + + this.attack = function (card) { + console.log('' + card.value) + const attack_value = card.value + let damages = attack_value + let shield_event = '' + + // Shield + if (this.shield.value > 0) { + // Damaged shield + if (this.shield.is_damaged() === true && attack_value >= this.shield.break_limit) { + this.shield.value = 0 + this.shield.break_limit = null + shield_event = 'your shield broke' + } else { + this.shield.break_limit = attack_value + damages = attack_value > this.shield.value ? Math.abs(attack_value - this.shield.value) : 0 + shield_event = `your shield absorbed ${damages < 1 ? 'everything' : attack_value > this.shield.value ? this.shield.value : attack_value}` + } + } + + // Damages went through + if (damages > 0) { + this.health.value -= damages + } + + // Timeline + if (this.health.value < 1) { + donsol.player.health.add_event('-' + damages) + donsol.timeline.add_event('The ' + card.name + ' killed you!') + donsol.board.dungeon_failed() + this.update() + } else { + donsol.timeline.add_event(`${damages > 0 ? 'Battled' : 'Killed'} the ${card.name}${shield_event !== '' ? ', ' + shield_event : ''}.`) + } + + // Experience + donsol.player.experience.add_event('+1') + + this.can_drink = true + donsol.is_complete = false + this.shield.update() + this.health.update() + } + + this.equip_shield = function (shield_value) { + console.log('' + shield_value) + + this.shield.value = shield_value + this.shield.break_limit = null + + // donsol.player.shield.add_event(shield_value); + donsol.player.experience.add_event('+1') + donsol.timeline.add_event('Equipped shield ' + shield_value + '.') + this.can_drink = true + donsol.is_complete = false + this.shield.update() + this.health.update() + } + + this.drink_potion = function (potion_value) { + console.log('' + potion_value) + + if (this.can_drink === false) { + donsol.timeline.add_event('Wasted potion!') + donsol.player.health.add_event('Wasted') + return + } + const before_health = this.health.value + let new_health = this.health.value + potion_value; new_health = new_health > 21 ? 21 : new_health + + const mod = new_health - before_health + donsol.player.health.value = new_health + donsol.player.health.add_event(mod > 0 ? '+' + mod : 'Wasted') + donsol.player.experience.add_event('+1') + donsol.timeline.add_event('Drank potion.') + this.can_drink = false + donsol.is_complete = false + this.health.update() + this.shield.update() + } + + this.escape_room = function () { + donsol.speaker.play_effect('click2') + if (this.health.value < 1 || donsol.is_complete === true || this.experience.value == 0) { + donsol.new_game() + return + } + if (this.can_escape() !== true) { + donsol.timeline.add_event('Cannot escape the room!') + return + } + + this.has_escaped = true + this.can_drink = true + + donsol.board.return_cards() + donsol.board.enter_room() + donsol.timeline.add_event('Escaped the room!') + } + + this.update = function () { + if (this.health.value < 1) { + this.escape_button.innerHTML = 'Restart' + this.element.setAttribute('class', 'death') + } else if (this.can_escape() === true) { + this.escape_button.innerHTML = 'Run' + this.element.setAttribute('class', 'unlocked') + } else { + this.escape_button.innerHTML = 'Locked' + this.element.setAttribute('class', 'locked') + } + + this.health.clear_event() + this.shield.clear_event() + this.experience.clear_event() + + this.health.update() + this.shield.update() + this.experience.update() + } + + this.can_escape = function () { + // Basic Overrides + if (this.health.value < 1) { return true } // Death + if (this.experience.value === 0) { return true } // New Game + + // - All monsters have been delt with. (Easy Mode) + // - The player has not escaped the previous room. (Normal Mode) + // - There is only one card left in the room. (Hard Mode) + // - Can never escape. (Expert Mode) + + // Easy + if (donsol.difficulty == 0) { + if (!this.has_escaped) { return true } + if (donsol.board.has_monsters()) { console.warn('Monsters present.'); return false } + return true + } + + // Normal + if (donsol.difficulty == 1) { + if (!this.has_escaped) { return true } + if (donsol.board.has_monsters()) { console.warn('Monsters present.'); return false } + return true + } + + // Hard + if (donsol.difficulty == 2) { + if (!this.has_escaped) { return true } + if (!donsol.board.cards_flipped().length != 3) { console.warn('Cards remain.'); return false } + if (donsol.board.has_monsters()) { console.warn('Monsters present.'); return false } + return true + } + + // Expert + if (donsol.difficulty == 3) { + console.warn('Cannot escape(expert).') + return false + } + + return false + } +} diff --git a/sources/scripts/speaker.js b/sources/scripts/speaker.js new file mode 100644 index 0000000..672ce0d --- /dev/null +++ b/sources/scripts/speaker.js @@ -0,0 +1,28 @@ +'use strict' + +function Speaker () { + this.effect = new Audio() + + this.audio_catalog = {} + + this.is_muted = false + + this.play_effect = function (name) { + this.effect = this.load(name, 'effect', `media/audio/effect/${name}.ogg`) + this.effect.play() + } + + this.load = function (name, role, src, loop = false) { + const audio_id = role + '_' + name + if (!(audio_id in this.audio_catalog)) { + const audio = new Audio() + audio.name = name + audio.src = src + audio.loop = loop + audio.mute = 'muted' + this.audio_catalog[audio_id] = audio + } + this.audio_catalog[audio_id].currentTime = 0 + return this.audio_catalog[audio_id] + } +} diff --git a/sources/scripts/timeline.js b/sources/scripts/timeline.js new file mode 100644 index 0000000..bc10843 --- /dev/null +++ b/sources/scripts/timeline.js @@ -0,0 +1,16 @@ +'use strict' + +function Timeline () { + this.el = document.createElement('div') + this.el.id = 'timeline' + + this.install = function (host) { + host.appendChild(this.el) + } + + this.add_event = function (message) { + this.el.className = '' + this.el.style.opacity = '0' + setTimeout(() => { this.el.style.opacity = 1; this.el.innerHTML = message }, 100) + } +} diff --git a/sources/scripts/walkthrough.js b/sources/scripts/walkthrough.js new file mode 100644 index 0000000..d033d88 --- /dev/null +++ b/sources/scripts/walkthrough.js @@ -0,0 +1,103 @@ +'use strict' + +function Walkthrough () { + this.is_running = false + this.speed = 2500 + + this.start = function () { + console.log('Started walkthrough') + this.is_running = true + } + + this.run = function (force = false) { + if (!this.is_running && !force) { return } // Idle + if (donsol.player.health.value < 1) { this.is_running = false; return } + + const results = this.rate_room(donsol.board.room) + const target = results[0] + + // Return if going to waste potions + if (target && target[1] < -10 && donsol.player.can_escape()) { + donsol.player.escape_room() + return + } + + if (target) { + donsol.board.room[target[[0]]].touch() + } + } + + this.rate_room = function (room) { + const a = [] + for (const id in room) { + const card = room[id] + if (card.is_flipped) { continue } + a.push(this.rate_card(id, card)) + } + return a.sort(function (a, b) { + return a[1] - b[1] + }).reverse() + } + + this.rate_card = function (id, card) { + let rating = 0 + if (card.type == 'diamond') { + if (donsol.player.shield.value > 0) { + rating = donsol.player.shield.value - card.value + } else { + rating = card.value + } + } + if (card.type == 'heart') { + // Will waste + if (!donsol.player.can_drink || donsol.player.health.value == 21) { + rating = -card.value * 4 + } else { + const after = clamp(donsol.player.health.value + card.value, 0, 21) + const actual = (donsol.player.health.value - after) + rating = actual - card.value + } + } + if (card.type == 'clove' || card.type == 'spade') { + const strongest = this.find_strongest(id) + if (card.value < strongest.value) { + rating = -strongest.value - card.value + } else { + rating = -card.value + } + + if (donsol.player.shield.limit > card.value) { + rating = donsol.player.shield.limit + } + } + // TODO: Run + // TODO: Attack in descending order + // TODO: Don't waste shields + return [parseInt(id), rating, card] + } + + this.find_strongest = function () { + let strongest = null + + for (const id in donsol.board.room) { + const card = donsol.board.room[id] + if (card.type == 'diamond' || card.type == 'heart') { continue } + if (card.is_flipped) { continue } + if (!strongest) { strongest = card; continue } + if (card.value > strongest.value) { strongest = card } + } + return strongest + } + + setInterval(() => { donsol.walkthrough.run() }, this.speed) + function clamp (v, min, max) { return v < min ? min : v > max ? max : v } +} + +document.onkeyup = (e) => { + if (e.ctrlKey && e.key.toLowerCase() == 'k') { + donsol.walkthrough.start() + } + if (e.ctrlKey && e.key.toLowerCase() == 'l') { + donsol.walkthrough.run(true) + } +}