mirror of https://github.com/bra1n/townsquare.git
added support for custom (base character) scripts
This commit is contained in:
parent
8fcf12d656
commit
061e7565e8
|
@ -86,6 +86,12 @@ export default {
|
||||||
url("assets/fonts/papyrus.svg#PapyrusW01") format("svg"); /* iOS 4.1- */
|
url("assets/fonts/papyrus.svg#PapyrusW01") format("svg"); /* iOS 4.1- */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: PiratesBay;
|
||||||
|
src: url("assets/fonts/piratesbay.ttf");
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
|
@ -121,6 +127,9 @@ h4,
|
||||||
h5 {
|
h5 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
font-family: PiratesBay, sans-serif;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 244 KiB |
Binary file not shown.
|
@ -4,8 +4,8 @@
|
||||||
Welcome to the (unofficial)
|
Welcome to the (unofficial)
|
||||||
<b> Virtual Blood on the Clocktower Town Square</b>!<br />
|
<b> Virtual Blood on the Clocktower Town Square</b>!<br />
|
||||||
Please add more players through the
|
Please add more players through the
|
||||||
<span class="button">
|
<span class="button" @click="toggleMenu">
|
||||||
<font-awesome-icon icon="cog" @click="toggleMenu" /> Menu
|
<font-awesome-icon icon="cog" /> Menu
|
||||||
</span>
|
</span>
|
||||||
on the top right or by pressing <b>[A]</b>.<br />
|
on the top right or by pressing <b>[A]</b>.<br />
|
||||||
This project is free and open source and can be found on
|
This project is free and open source and can be found on
|
||||||
|
|
|
@ -317,9 +317,10 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.headline {
|
.headline {
|
||||||
|
font-family: PiratesBay, sans-serif;
|
||||||
|
letter-spacing: 1px;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: bold;
|
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
to right,
|
to right,
|
||||||
$townsfolk 0%,
|
$townsfolk 0%,
|
||||||
|
|
|
@ -243,6 +243,10 @@ export default {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#townsquare.spectator & {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
#townsquare:not(.spectator) &:hover:before {
|
#townsquare:not(.spectator) &:hover:before {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
top: -10px;
|
top: -10px;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
v-show="modals.edition"
|
v-show="modals.edition"
|
||||||
@close="toggleModal('edition')"
|
@close="toggleModal('edition')"
|
||||||
>
|
>
|
||||||
|
<div v-if="!isCustom">
|
||||||
<h3>Select an edition:</h3>
|
<h3>Select an edition:</h3>
|
||||||
<ul class="editions">
|
<ul class="editions">
|
||||||
<li
|
<li
|
||||||
|
@ -15,7 +16,48 @@
|
||||||
>
|
>
|
||||||
{{ edition.name }}
|
{{ edition.name }}
|
||||||
</li>
|
</li>
|
||||||
|
<li class="edition edition-custom" @click="isCustom = true">
|
||||||
|
Custom Edition
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="custom" v-else>
|
||||||
|
<h3>Select a custom edition</h3>
|
||||||
|
To play with a custom script, you need to select the characters you want
|
||||||
|
to play with in the official
|
||||||
|
<a href="https://bloodontheclocktower.com/script-tool/" target="_blank"
|
||||||
|
>Script Tool</a
|
||||||
|
>
|
||||||
|
and then upload the generated "custom-list.json" either directly here or
|
||||||
|
provide a URL to such a hosted JSON file.<br />
|
||||||
|
<h3>Some custom Teensyville scripts:</h3>
|
||||||
|
<ul class="scripts">
|
||||||
|
<li
|
||||||
|
v-for="(script, index) in scripts"
|
||||||
|
v-bind:key="index"
|
||||||
|
@click="handleURL(script[1])"
|
||||||
|
>
|
||||||
|
{{ script[0] }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
ref="upload"
|
||||||
|
accept="application/json"
|
||||||
|
@change="handleUpload"
|
||||||
|
/>
|
||||||
|
<div class="button-group">
|
||||||
|
<div class="button" @click="openUpload">
|
||||||
|
<font-awesome-icon icon="file-upload" /> Upload JSON
|
||||||
|
</div>
|
||||||
|
<div class="button" @click="promptURL">
|
||||||
|
<font-awesome-icon icon="link" /> Enter URL
|
||||||
|
</div>
|
||||||
|
<div class="button" @click="isCustom = false">
|
||||||
|
<font-awesome-icon icon="undo" /> Back
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -30,11 +72,57 @@ export default {
|
||||||
},
|
},
|
||||||
data: function() {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
editions: editionJSON
|
editions: editionJSON,
|
||||||
|
isCustom: false,
|
||||||
|
scripts: [
|
||||||
|
[
|
||||||
|
"On Thin Ice",
|
||||||
|
"https://gist.githubusercontent.com/bra1n/8dacd9f2abc6f428331ea1213ab153f5/raw/9758aff4b59965dc7a094db549d950be5a26b571/custom-script.json"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Race To The Bottom",
|
||||||
|
"https://gist.githubusercontent.com/bra1n/63e1354cb3dc9d4032bcd0623dc48888/raw/5be4df8386ec61e3a98c32be77f8cac3f8414379/custom-script.json"
|
||||||
|
]
|
||||||
|
]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: mapState(["modals"]),
|
computed: mapState(["modals"]),
|
||||||
methods: mapMutations(["toggleModal", "setEdition"])
|
methods: {
|
||||||
|
openUpload() {
|
||||||
|
this.$refs.upload.click();
|
||||||
|
},
|
||||||
|
handleUpload() {
|
||||||
|
const file = this.$refs.upload.files[0];
|
||||||
|
if (file && file.size) {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.addEventListener("load", () => {
|
||||||
|
this.parseScript(JSON.parse(reader.result));
|
||||||
|
});
|
||||||
|
reader.readAsText(file);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
promptURL() {
|
||||||
|
const url = prompt("Enter URL to a custom-script.JSON");
|
||||||
|
if (url) {
|
||||||
|
this.handleURL(url);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async handleURL(url) {
|
||||||
|
const res = await fetch(url);
|
||||||
|
if (res && res.json) {
|
||||||
|
const script = await res.json();
|
||||||
|
this.parseScript(script);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
parseScript(script) {
|
||||||
|
if (!script || !script.length) return;
|
||||||
|
const roles = script.map(({ id }) => id);
|
||||||
|
this.$store.commit("setRoles", roles);
|
||||||
|
this.$store.commit("setEdition", "custom");
|
||||||
|
this.isCustom = false;
|
||||||
|
},
|
||||||
|
...mapMutations(["toggleModal", "setEdition"])
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -63,15 +151,16 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.editions .edition {
|
ul.editions .edition {
|
||||||
|
font-family: PiratesBay, sans-serif;
|
||||||
|
letter-spacing: 1px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-top: 100px;
|
padding-top: 100px;
|
||||||
background-position: center center;
|
background-position: center center;
|
||||||
background-size: 100% auto;
|
background-size: 100% auto;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
width: 200px;
|
width: 30%;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
font-size: 120%;
|
font-size: 120%;
|
||||||
font-weight: bold;
|
|
||||||
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000,
|
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000,
|
||||||
1px 1px 0 #000, 0 0 5px rgba(0, 0, 0, 0.75);
|
1px 1px 0 #000, 0 0 5px rgba(0, 0, 0, 0.75);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -79,4 +168,23 @@ ul.editions .edition {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.custom {
|
||||||
|
text-align: center;
|
||||||
|
input[type="file"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.scripts {
|
||||||
|
list-style-type: disc;
|
||||||
|
font-size: 120%;
|
||||||
|
cursor: pointer;
|
||||||
|
display: block;
|
||||||
|
width: 50%;
|
||||||
|
text-align: left;
|
||||||
|
margin: 10px auto;
|
||||||
|
li:hover {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
10
src/main.js
10
src/main.js
|
@ -23,7 +23,10 @@ import {
|
||||||
faBroadcastTower,
|
faBroadcastTower,
|
||||||
faCopy,
|
faCopy,
|
||||||
faExchangeAlt,
|
faExchangeAlt,
|
||||||
faHandPointRight
|
faHandPointRight,
|
||||||
|
faFileUpload,
|
||||||
|
faLink,
|
||||||
|
faUndo
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||||
|
|
||||||
|
@ -48,7 +51,10 @@ library.add(
|
||||||
faBroadcastTower,
|
faBroadcastTower,
|
||||||
faCopy,
|
faCopy,
|
||||||
faExchangeAlt,
|
faExchangeAlt,
|
||||||
faHandPointRight
|
faHandPointRight,
|
||||||
|
faFileUpload,
|
||||||
|
faLink,
|
||||||
|
faUndo
|
||||||
);
|
);
|
||||||
|
|
||||||
Vue.component("font-awesome-icon", FontAwesomeIcon);
|
Vue.component("font-awesome-icon", FontAwesomeIcon);
|
||||||
|
|
|
@ -86,6 +86,7 @@ export default new Vuex.Store({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
toggleModal({ modals }, name) {
|
toggleModal({ modals }, name) {
|
||||||
|
console.log("toggle", name);
|
||||||
modals[name] = !modals[name];
|
modals[name] = !modals[name];
|
||||||
},
|
},
|
||||||
updateScreenshot({ grimoire }, status) {
|
updateScreenshot({ grimoire }, status) {
|
||||||
|
@ -97,11 +98,21 @@ export default new Vuex.Store({
|
||||||
grimoire.isScreenshot = false;
|
grimoire.isScreenshot = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setRoles(state, roles) {
|
||||||
|
state.roles = new Map(
|
||||||
|
rolesJSON
|
||||||
|
.filter(r => roles.includes(r.id))
|
||||||
|
.sort((a, b) => b.team.localeCompare(a.team))
|
||||||
|
.map(role => [role.id, role])
|
||||||
|
);
|
||||||
|
},
|
||||||
setEdition(state, edition) {
|
setEdition(state, edition) {
|
||||||
state.edition = edition;
|
state.edition = edition;
|
||||||
state.modals.edition = false;
|
state.modals.edition = false;
|
||||||
|
if (edition !== "custom") {
|
||||||
state.roles = getRolesByEdition(edition);
|
state.roles = getRolesByEdition(edition);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
plugins: [persistence, session]
|
plugins: [persistence, session]
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,6 +10,9 @@ module.exports = store => {
|
||||||
// this will initialize state.roles!
|
// this will initialize state.roles!
|
||||||
store.commit("setEdition", localStorage.edition);
|
store.commit("setEdition", localStorage.edition);
|
||||||
}
|
}
|
||||||
|
if (localStorage.roles !== undefined) {
|
||||||
|
store.commit("setRoles", JSON.parse(localStorage.roles));
|
||||||
|
}
|
||||||
if (localStorage.bluffs !== undefined) {
|
if (localStorage.bluffs !== undefined) {
|
||||||
JSON.parse(localStorage.bluffs).forEach((role, index) => {
|
JSON.parse(localStorage.bluffs).forEach((role, index) => {
|
||||||
store.commit("setBluff", {
|
store.commit("setBluff", {
|
||||||
|
@ -50,7 +53,19 @@ module.exports = store => {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "setEdition":
|
case "setEdition":
|
||||||
|
if (payload === "custom") {
|
||||||
|
localStorage.removeItem("edition");
|
||||||
|
} else {
|
||||||
localStorage.setItem("edition", payload);
|
localStorage.setItem("edition", payload);
|
||||||
|
localStorage.removeItem("roles");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "setRoles":
|
||||||
|
if (!payload.length) {
|
||||||
|
localStorage.removeItem("roles");
|
||||||
|
} else {
|
||||||
|
localStorage.setItem("roles", JSON.stringify(payload));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "setBluff":
|
case "setBluff":
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
|
|
|
@ -9,5 +9,6 @@ $editions:
|
||||||
'tb',
|
'tb',
|
||||||
'bmr',
|
'bmr',
|
||||||
'snv',
|
'snv',
|
||||||
'luf' true
|
'luf' true,
|
||||||
|
'custom' true
|
||||||
;
|
;
|
||||||
|
|
Loading…
Reference in New Issue