Stream types now change via the kiosk

This commit is contained in:
thepaperpilot 2023-02-28 19:54:46 -06:00
parent d70ed118c4
commit 06f50b3308
12 changed files with 305 additions and 65 deletions

View file

@ -76,6 +76,13 @@
<link rel="prefetch" href="aimen coots.png" />
<link rel="prefetch" href="mogul moves coots.png" />
<link rel="prefetch" href="stream type.png" />
<link rel="prefetch" href="kitchen_small.png" />
<link rel="prefetch" href="react_small.png" />
<link rel="prefetch" href="room_small.png" />
<link rel="prefetch" href="show_small.png" />
<link rel="prefetch" href="yard_small.png" />
<link rel="prefetch" href="shop_Switch1.png" />
<link rel="prefetch" href="Fire.png" />
<title>Profectus</title>
<meta name="description" content="A project made in Profectus"/>

BIN
public/Fire.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 B

BIN
public/kitchen_small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
public/react_small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
public/room_small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
public/shop_Switch1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
public/show_small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
public/yard_small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -131,16 +131,19 @@
}
.stream-types .row > * {
flex-grow: 1;
margin-right: auto;
width: 16vmin;
}
.stream-type {
display: flex;
flex-direction: column;
padding: 1vmin 0 0.5vmin 0;
cursor: pointer;
width: 100%;
font-size: 2vmin;
aspect-ratio: 1.5/1;
padding: 1vmin;
user-select: none;
}
.stream-type.active {
@ -149,8 +152,7 @@
}
.stream-type img {
width: 6vmin;
aspect-ratio: 1/1;
width: 9vmin;
image-rendering: pixelated;
}
@ -158,6 +160,28 @@
margin-left: -32vmin;
}
.stream-type.selected::before {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' stroke='%23000' stroke-width='12' stroke-dasharray='10%25%2c105%2510%25%2c72%2510%25%2c105%2510%25%2c72%2510%25' stroke-dashoffset='5%25' stroke-linecap='square'/%3e%3c/svg%3e");
z-index: 100;
}
.stream-type:not(.selected):hover::before {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' stroke='%23000' stroke-width='8' stroke-dasharray='10%25%2c105%2510%25%2c72%2510%25%2c105%2510%25%2c72%2510%25' stroke-dashoffset='5%25' stroke-linecap='square'/%3e%3c/svg%3e");
z-index: 100;
}
.shop {
position: relative;
filter: drop-shadow(2px 4px 6px black);

View file

@ -12,8 +12,10 @@ import settings from "game/settings";
import { formatWhole } from "util/bignum";
import { render } from "util/vue";
import { computed, ref, TransitionGroup, watch } from "vue";
import type { WatchStopHandle } from "vue";
import aimen from "../../public/aimen coots.png";
import autoplay from "../../public/autoplay.png";
import game from "../../public/bro vs bro bg.png";
import connor from "../../public/cdawg va.png";
import chessboxing from "../../public/chessboxing coots.png";
import defeatButton from "../../public/Defeat Button.png";
@ -25,6 +27,7 @@ import hasan from "../../public/hasan coots.png";
import heart_small from "../../public/heart_small.png";
import ironmouse from "../../public/ironmouse coots.png";
import kitchen from "../../public/Kitchen BG.png";
import kitchen_small from "../../public/kitchen_small.png";
import reaction from "../../public/lud's room bg.png";
import luddy from "../../public/luddy Coots.png";
import ludwig from "../../public/Ludwig Coots.png";
@ -42,28 +45,34 @@ import playAgain from "../../public/Play Again.png";
import play from "../../public/play.png";
import star_small from "../../public/presence_small.png";
import qt from "../../public/QT Coots.png";
import react_small from "../../public/react_small.png";
import room_small from "../../public/room_small.png";
import shopGif from "../../public/shop.gif";
import shopStill from "../../public/shop1.png";
import sellShop from "../../public/shop_Sell1.png";
import show_small from "../../public/show_small.png";
import shop_Switch1 from "../../public/shop_Switch1.png";
import slime from "../../public/SlimeCoots.png";
import smash from "../../public/smash coots.png";
import stanz from "../../public/Stanz Coots.png";
import startStream from "../../public/start stream.png";
import awards from "../../public/streamer award coots.png";
import yard from "../../public/the yard bg.png";
import game from "../../public/bro vs bro bg.png";
import tieButton from "../../public/Tie Button.png";
import vespa from "../../public/Vespa Coots.png";
import victoryButton from "../../public/Victory Button.png";
import victoryFace from "../../public/win face.png";
import yard_small from "../../public/yard_small.png";
import CharacterSlot from "./CharacterSlot.vue";
import "./common.css";
import healthParticles from "./health.json";
import presenceParticles from "./presence.json";
import "./socket";
import { emit, nickname, poof } from "./socket";
import type { AbilityTypes, BattleOutcome, Character, CharacterInfo, StreamTypes } from "./types";
import victoryParticles from "./victory.json";
import healthParticles from "./health.json";
import presenceParticles from "./presence.json";
import spellParticles from "./spellparticles.json";
import Node from "components/Node.vue";
const streamTypeToBG: Record<StreamTypes, string> = {
"Game Show": gameshow,
@ -780,6 +789,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
const shop = ref<(Character | null)[]>([]);
const selectedCharacter = ref<number | null>(null);
const selectedShopItem = ref<number | null>(null);
const selectedStreamType = ref<StreamTypes | null>(null);
const findingMatch = ref<boolean>(false);
const outcome = ref<BattleOutcome | "">("");
const showingOutcome = ref<boolean>(false);
@ -841,6 +851,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
shop.value = [];
selectedCharacter.value = null;
selectedShopItem.value = null;
selectedStreamType.value = null;
findingMatch.value = false;
battle.value = null;
outcome.value = "";
@ -977,6 +988,11 @@ export const main = createLayer("main", function (this: BaseLayer) {
boundingRect: ref<null | DOMRect>(null),
onContainerResized(boundingRect) {
this.boundingRect.value = boundingRect;
},
onHotReload() {
shopParticleEmitter.value.then(e => e.destroy());
shopParticleEmitter.value = particles.addEmitter(spellParticles);
updateShopParticles();
}
}));
@ -989,6 +1005,79 @@ export const main = createLayer("main", function (this: BaseLayer) {
}
});
const shopParticleEmitter = ref(particles.addEmitter(spellParticles));
const shopTooltip = computed(() => {
if (selectedCharacter.value != null) {
return "Sell Coots";
} else if (selectedShopItem.value != null) {
return "Freeze Coots";
} else if (selectedStreamType.value != null) {
return "Switch Stream Type";
}
return "Re-Roll Shop";
});
const shopImage = computed(() => {
if (selectedCharacter.value != null) {
return sellShop;
} else if (selectedShopItem.value != null) {
return freezeShop;
} else if (selectedStreamType.value != null) {
return shop_Switch1;
}
return showRefreshAnim.value ? shopGif : shopStill;
});
const handleShop = () => {
if (selectedCharacter.value != null) {
emit("sell", selectedCharacter.value!);
} else if (selectedShopItem.value != null) {
emit("freeze", selectedShopItem.value!);
} else if (selectedStreamType.value != null) {
if (gold.value > 2) {
emit("change stream type", selectedStreamType.value);
}
} else {
if (gold.value > 0) {
emit("reroll");
}
}
};
const shouldShowParticles = computed(
() =>
selectedCharacter.value != null ||
selectedShopItem.value != null ||
(selectedStreamType.value != null && selectedStreamType.value != streamType.value)
);
const particleEffectWatcher = ref<null | WatchStopHandle>(null);
const updateShopParticles = async () => {
const particle = await shopParticleEmitter.value;
particleEffectWatcher.value?.();
if (shouldShowParticles.value) {
particle.emit = true;
particleEffectWatcher.value = watch(
[() => main.nodes.value.reroll?.rect, particles.boundingRect],
async ([rect, boundingRect]) => {
if (rect != null && boundingRect != null) {
particle.cleanup();
particle.updateOwnerPos(
rect.x + rect.width / 2 - boundingRect.x,
rect.y + rect.height / 2 - boundingRect.y
);
particle.resetPositionTracking();
particle.emit = true;
} else {
particle.emit = false;
}
},
{ immediate: true }
);
} else {
particle.emit = false;
particleEffectWatcher.value = null;
}
};
watch(shouldShowParticles, updateShopParticles);
return {
name: "Game",
minimizable: false,
@ -1271,47 +1360,17 @@ export const main = createLayer("main", function (this: BaseLayer) {
))}
</Row>
<Row style="margin-top: 2vh" class="no-margin">
{selectedCharacter.value != null ? (
<Tooltip display="Sell Coots">
<div
class="reroll"
onDragover={e => e.preventDefault()}
onClick={() => emit("sell", selectedCharacter.value!)}
onDrop={() => emit("sell", selectedCharacter.value!)}
>
<img src={sellShop} />
</div>
</Tooltip>
) : selectedShopItem.value != null ? (
<Tooltip display="Freeze Coots">
<div
class="reroll"
onDragover={e => e.preventDefault()}
onClick={() => emit("freeze", selectedShopItem.value!)}
onDrop={() => emit("freeze", selectedShopItem.value!)}
>
<img src={freezeShop} />
</div>
</Tooltip>
) : (
<Tooltip display="Re-roll store">
<div
class="reroll"
style={
gold.value > 0
? ""
: "color: var(--locked); cursor: not-allowed"
}
onClick={() => {
if (gold.value > 0) {
emit("reroll");
}
}}
>
<img src={showRefreshAnim.value ? shopGif : shopStill} />
</div>
</Tooltip>
)}
<Tooltip display={shopTooltip.value}>
<div
class="reroll"
onDragover={e => e.preventDefault()}
onClick={handleShop}
onDrop={handleShop}
>
<img src={shopImage.value} />
<Node id="reroll" />
</div>
</Tooltip>
<Row class="shop">
{shop.value.map((item, i) => (
<CharacterSlot
@ -1349,12 +1408,13 @@ export const main = createLayer("main", function (this: BaseLayer) {
<div
class={{
"stream-type": true,
active: streamType.value === "Game Show"
active: streamType.value === "Game Show",
selected: selectedStreamType.value === "Game Show"
}}
onClick={() => emit("change stream type", "Game Show")}
onClick={clickStreamType("Game Show")}
>
<img src={gameshow} />
<span>Game Show</span>
<img src={show_small} />
<span>Show</span>
</div>
</Tooltip>
<Tooltip
@ -1369,12 +1429,13 @@ export const main = createLayer("main", function (this: BaseLayer) {
<div
class={{
"stream-type": true,
active: streamType.value === "Reaction Stream"
active: streamType.value === "Reaction Stream",
selected: selectedStreamType.value === "Reaction Stream"
}}
onClick={() => emit("change stream type", "Reaction Stream")}
onClick={clickStreamType("Reaction Stream")}
>
<img src={reaction} />
<span>Coots</span>
<img src={room_small} />
<span>Play</span>
</div>
</Tooltip>
<Tooltip
@ -1390,11 +1451,12 @@ export const main = createLayer("main", function (this: BaseLayer) {
<div
class={{
"stream-type": true,
active: streamType.value === "Podcast"
active: streamType.value === "Podcast",
selected: selectedStreamType.value === "Podcast"
}}
onClick={() => emit("change stream type", "Podcast")}
onClick={clickStreamType("Podcast")}
>
<img src={yard} />
<img src={yard_small} />
<span>Podcast</span>
</div>
</Tooltip>
@ -1413,11 +1475,12 @@ export const main = createLayer("main", function (this: BaseLayer) {
<div
class={{
"stream-type": true,
active: streamType.value === "Cooking Stream"
active: streamType.value === "Cooking Stream",
selected: selectedStreamType.value === "Cooking Stream"
}}
onClick={() => emit("change stream type", "Cooking Stream")}
onClick={clickStreamType("Cooking Stream")}
>
<img src={kitchen} />
<img src={kitchen_small} />
<span>Cooking</span>
</div>
</Tooltip>
@ -1435,11 +1498,12 @@ export const main = createLayer("main", function (this: BaseLayer) {
<div
class={{
"stream-type": true,
active: streamType.value === "Bro vs Bro"
active: streamType.value === "Bro vs Bro",
selected: selectedStreamType.value === "Bro vs Bro"
}}
onClick={() => emit("change stream type", "Bro vs Bro")}
onClick={clickStreamType("Bro vs Bro")}
>
<img src={game} />
<img src={react_small} />
<span>Reaction</span>
</div>
</Tooltip>
@ -1456,6 +1520,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
shop,
selectedCharacter,
selectedShopItem,
selectedStreamType,
findingMatch,
showingOutcome,
outcome,
@ -1497,6 +1562,7 @@ globalBus.on("update", diff => {
function clickCharacter(index: number) {
return (e?: MouseEvent) => {
main.selectedStreamType.value = null;
if (main.selectedCharacter.value != null && main.selectedCharacter.value !== index) {
if (
main.team.value[main.selectedCharacter.value]?.type ===
@ -1530,6 +1596,17 @@ function clickCharacter(index: number) {
};
}
function clickStreamType(type: StreamTypes) {
return (e?: MouseEvent) => {
if (main.selectedStreamType.value == null || main.selectedStreamType.value !== type) {
main.selectedStreamType.value = type;
} else {
main.selectedStreamType.value = null;
}
e?.stopPropagation();
};
}
/**
* Given a player save data object being loaded, return a list of layers that should currently be enabled.
* If your project does not use dynamic layers, this should just return all layers.

View file

@ -274,6 +274,7 @@ function setupSocket(socket: Socket<ServerToClientEvents, ClientToServerEvents>)
});
socket.on("stream type", (type, charged) => {
main.streamType.value = type;
main.selectedStreamType.value = null;
if (charged) {
main.gold.value -= 3;
}

View file

@ -0,0 +1,131 @@
{
"emit": false,
"autoUpdate": true,
"lifetime": {
"min": 0.5,
"max": 2
},
"frequency": 0.005,
"emitterLifetime": -1,
"maxParticles": 1000,
"addAtBack": true,
"pos": {
"x": 0,
"y": 0
},
"behaviors": [
{
"type": "alpha",
"config": {
"alpha": {
"list": [
{
"time": 0,
"value": 1
},
{
"time": 1,
"value": 0
}
]
}
}
},
{
"type": "moveSpeed",
"config": {
"speed": {
"list": [
{
"time": 0,
"value": 2
},
{
"time": 1,
"value": 25
}
]
},
"minMult": 2
}
},
{
"type": "scale",
"config": {
"scale": {
"list": [
{
"time": 0,
"value": 0.001
},
{
"time": 1,
"value": 1
}
]
},
"minMult": 0.25
}
},
{
"type": "color",
"config": {
"color": {
"list": [
{
"time": 0,
"value": "#EB428F"
},
{
"time": 0.25,
"value": "#F545ED"
},
{
"time": 0.5,
"value": "#B949DE"
},
{
"time": 0.75,
"value": "#9945F5"
},
{
"time": 1,
"value": "#6442EB"
}
]
}
}
},
{
"type": "rotation",
"config": {
"accel": 0,
"minSpeed": 0,
"maxSpeed": 20,
"minStart": 270,
"maxStart": 300
}
},
{
"type": "textureRandom",
"config": {
"textures": [
"/Fire.png"
]
}
},
{
"type": "spawnShape",
"config": {
"type": "torus",
"data": {
"x": 0,
"y": 0,
"radius": 75,
"innerRadius": 75,
"affectRotation": true
}
}
}
]
}