Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sound effects #655

Merged
merged 12 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions client/app/cards/Login/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const Login = () => {
label="Login Name"
className="w-72"
onChange={(e) => setLoginName(e.target.value)}
autoComplete="off"
autoCorrect="off"
value={loginName}
/>
<Button
Expand Down
31 changes: 31 additions & 0 deletions client/app/cards/Pilot/data.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { pubsub } from "@server/init/pubsub";
import { getShipSystem } from "@server/utils/getShipSystem";
import { z } from "zod";
import type { Entity } from "@server/utils/ecs";
import {
cancelLoopingSound,
playShipSound,
} from "@server/utils/playRangedSound";

export const pilot = t.router({
impulseEngines: t.router({
Expand All @@ -29,6 +33,19 @@ export const pilot = t.router({
impulseEngines.components.isImpulseEngines?.emergencySpeed || 1,
};
}),
ambiance: t.procedure.request(({ ctx }) => {
const engine = getShipSystem(ctx, { systemType: "impulseEngines" });
const { currentPower, requiredPower, maxSafePower } = engine.components
.power || { currentPower: 0, requiredPower: 0, maxSafePower: 0 };
return [
{
id: engine.id,
volumePercent: Math.min(1, currentPower / requiredPower),
playbackRate: currentPower / maxSafePower,
ambiance: engine.components.soundEffects?.soundBank.ambiance,
},
];
}),
setSpeed: t.procedure
.input(z.object({ systemId: z.number().optional(), speed: z.number() }))
.send(({ ctx, input }) => {
Expand Down Expand Up @@ -244,6 +261,13 @@ export const pilot = t.router({
},
});

if (!input.direction.x && !input.direction.y && !input.direction.z) {
// Cancel the looping sound
cancelLoopingSound(system, "thrust");
} else if (system.components.soundEffects?.soundBank.thrust) {
playShipSound(system, ctx.ship!, "thrust");
}

return system;
}),
setRotationDelta: t.procedure
Expand Down Expand Up @@ -283,6 +307,13 @@ export const pilot = t.router({
},
});

if (!input.rotation.x && !input.rotation.y && !input.rotation.z) {
// Cancel the looping sound
cancelLoopingSound(system, "thrust");
} else if (system.components.soundEffects?.soundBank.thrust) {
playShipSound(system, ctx.ship!, "thrust");
}

// TODO: September 21 2022 - Deactivate the ships autopilot when the thruster rotation change
return system;
}),
Expand Down
14 changes: 14 additions & 0 deletions client/app/cards/SystemsMonitor/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,23 @@ export const systemsMonitor = t.router({
reserve,
fuel: r.components.isReactor!.unusedFuel.amount || 0,
efficiency: r.components.efficiency?.efficiency,
ambiance: r.components.soundEffects?.soundBank.ambiance,
};
});
}),
ambiance: t.procedure.request(({ ctx }) => {
const reactors = getShipSystems(ctx, { systemType: "reactor" });

return reactors.map((r) => ({
id: r.id,
// Reactor volume is based on the ratio of the current output to the max output
volumePercent:
r.components.isReactor!.currentOutput /
r.components.isReactor!.maxOutput,
playbackRate: 1,
ambiance: r.components.soundEffects?.soundBank.ambiance,
}));
}),
}),
batteries: t.router({
get: t.procedure
Expand Down
6 changes: 0 additions & 6 deletions client/app/cards/SystemsMonitor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@ import {
} from "react";
import { Fragment } from "react/jsx-runtime";

/**
* TODO:
* - Reactor boxes should turn yellow based on the amount of power being used by batteries or systems
* - Which means there needs to be more data indicating where power is allocated
*
*/
export function SystemsMonitor({ cardLoaded }: CardProps) {
const [reactors] = q.systemsMonitor.reactors.get.useNetRequest();
const [batteries] = q.systemsMonitor.batteries.get.useNetRequest();
Expand Down
2 changes: 1 addition & 1 deletion client/app/cards/Targeting/Phasers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export function BeamVisualization() {
return (
<Line
ref={lineRef}
points={[0, 0, 0]}
points={[0, 0, 0, 0, 0, 0]}
segments
color="orange"
lineWidth={5}
Expand Down
46 changes: 36 additions & 10 deletions client/app/cards/Targeting/data.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ import { getInventoryTemplates } from "@server/utils/getInventoryTemplates";
import { randomFromList } from "@server/utils/randomFromList";
import { spawnTorpedo } from "@server/spawners/torpedo";
import type { Entity } from "@server/utils/ecs";
import { getCurrentTarget } from "@server/systems/PhasersSystem";
import {
getCurrentTarget,
getTargetIsInPhaserRange,
} from "@server/systems/PhasersSystem";
import { LiveQueryError } from "@thorium/live-query/client/client";

cancelLoopingSound,
playShipSound,
} from "@server/utils/playRangedSound";
export const targeting = t.router({
targetedContact: t.procedure
.filter((publish: { shipId: number }, { ctx }) => {
Expand Down Expand Up @@ -156,7 +155,6 @@ export const targeting = t.router({
) {
throw new Error("Torpedo launcher is not loaded");
}
launcher.components.isTorpedoLauncher.torpedoEntity;
const torpedoEntity = adjustTorpedoInventory(
ctx.ship,
input.torpedoId,
Expand All @@ -171,6 +169,14 @@ export const targeting = t.router({
pubsub.publish.targeting.torpedoes.launchers({
shipId: ctx.ship!.id,
});

if (torpedoEntity) {
cancelLoopingSound(launcher, "unload");
playShipSound(launcher, ctx.ship, "load");
} else {
cancelLoopingSound(launcher, "load");
playShipSound(launcher, ctx.ship, "unload");
}
}),
fire: t.procedure
.input(
Expand Down Expand Up @@ -225,6 +231,8 @@ export const targeting = t.router({
pubsub.publish.starmapCore.torpedos({
systemId: torpedo.components.position?.parentId || null,
});

playShipSound(launcher, ctx.ship!, "fire");
}),
}),
hull: t.procedure
Expand Down Expand Up @@ -429,17 +437,35 @@ export const targeting = t.router({
phaser.updateComponent("isPhasers", {
firePercent: input.firePercent,
});
const currentPower =
phaser.components.power?.powerSources.reduce((acc, id) => {
const powerSource = ctx.flight?.ecs.getEntityById(id);
if (powerSource?.components.isPhaseCapacitor) {
return acc + (powerSource.components.isBattery?.storage || 0);
}
return acc;
}, 0) || 0;

const ship = ctx.flight?.ecs.getEntityById(
phaser.components.isShipSystem?.shipId || -1,
);
pubsub.publish.targeting.phasers.firing({
shipId: ship!.id,
systemId: ship?.components.position?.parentId || null,
});

pubsub.publish.targeting.phasers.list({
shipId: phaser.components.isShipSystem?.shipId || -1,
});

if (input.firePercent === 0 || currentPower < 0.01) {
cancelLoopingSound(phaser, "fire");
} else {
pubsub.publish.targeting.phasers.firing({
shipId: ship!.id,
systemId: ship?.components.position?.parentId || null,
});

if (phaser.components.soundEffects?.soundBank.fire) {
playShipSound(phaser, ship!, "fire");
}
}
}),
}),
stream: t.procedure.dataStream(({ entity, ctx }) => {
Expand Down
92 changes: 92 additions & 0 deletions client/app/components/ui/RangeInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { cn } from "@client/utils/cn";
import type React from "react";
import type { ReactNode } from "react";

export const RangeInput = (
props: Omit<
React.InputHTMLAttributes<HTMLInputElement>,
"value" | "defaultValue" | "placeholder" | "onBlur"
> & {
label: ReactNode;
labelHidden?: boolean;
isInvalid?: boolean;
invalidMessage?: string;
fixed?: boolean;
labelProps?: React.LabelHTMLAttributes<HTMLLabelElement>;
helperText?: string;
value?: [number, number];
defaultValue?: [number, number];
placeholder?: [string, string];
onBlur?: (values: [number, number]) => void;
},
) => {
const {
label,
labelHidden = false,
isInvalid,
invalidMessage,
fixed,
labelProps,
value,
defaultValue,
helperText,
placeholder,
onBlur,
...inputProps
} = props;

return (
<div className={`flex flex-col ${fixed ? "" : "w-full"}`}>
<label
{...labelProps}
className={`${labelProps?.className || ""} ${
labelHidden ? "hidden" : ""
}`}
>
{label}
</label>
<div className="flex justify-between w-full gap-2">
<input
autoComplete="off"
{...(inputProps as React.InputHTMLAttributes<HTMLInputElement>)}
value={value?.[0]}
defaultValue={defaultValue?.[0]}
placeholder={placeholder?.[0]}
className={cn("flex-1 input w-full", inputProps.className, {
"border-red-500": isInvalid,
})}
onBlur={(event) => {
if (Number.isNaN(Number.parseFloat(event.target.value))) return;
onBlur?.([
Number(event.target.value),
value?.[1] ?? defaultValue?.[1] ?? 1,
]);
}}
/>
<input
autoComplete="off"
{...(inputProps as React.InputHTMLAttributes<HTMLInputElement>)}
value={value?.[0]}
defaultValue={defaultValue?.[1]}
placeholder={placeholder?.[1]}
className={cn("flex-1 input w-full", inputProps.className, {
"border-red-500": isInvalid,
})}
onBlur={(event) => {
if (Number.isNaN(Number.parseFloat(event.target.value))) return;
onBlur?.([
value?.[0] ?? defaultValue?.[0] ?? 1,
Number(event.target.value),
]);
}}
/>
</div>
{isInvalid && <p className="text-red-500">{invalidMessage}</p>}
{helperText && (
<p className="text-gray-400 text-sm leading-tight mb-2">{helperText}</p>
)}
</div>
);
};

RangeInput.displayName = "RangeInput";
3 changes: 3 additions & 0 deletions client/app/components/ui/icons/name.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
export const iconNames = [
"zap",
"x",
"volume-2",
"text-cursor-input",
"sword",
"star",
"speaker",
"sparkles",
"siren",
"shield-half",
"settings",
"route",
"rocket",
"repeat-2",
Expand Down
43 changes: 43 additions & 0 deletions client/app/components/ui/icons/sprite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading