Skip to content
This repository has been archived by the owner on Dec 16, 2021. It is now read-only.

Commit

Permalink
Make fast walls opt-in, add documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
joshwcomeau committed Nov 11, 2019
1 parent b87949d commit e2b1f62
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 9 deletions.
7 changes: 5 additions & 2 deletions src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,9 @@ export const updateGrid = (numCols, numRows, colWidth, rowHeight) => ({
rowHeight,
});

export const toggleFastWalls = () => ({
type: 'TOGGLE_FAST_WALLS',
export const toggleFastWallsForSelectedObstacles = () => ({
type: 'TOGGLE_FAST_WALLS_FOR_SELECTED_OBSTACLES',
});
export const toggleFastWallsEnabledForSong = () => ({
type: 'TOGGLE_FAST_WALLS_ENABLED_FOR_SONG',
});
2 changes: 2 additions & 0 deletions src/components/Docs/Docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import ManualDemo from './pages/ManualDemo';
import ManualPublishing from './pages/ManualDownloadingPublishing';
import Migrating from './pages/Migrating';
import Mods from './pages/Mods';
import FastWalls from './pages/FastWalls';
import Privacy from './pages/Privacy';
import ContentPolicy from './pages/ContentPolicy';

Expand All @@ -32,6 +33,7 @@ const Docs = () => {
<Route path="/docs/manual/publishing" component={ManualPublishing} />
<Route path="/docs/migrating" component={Migrating} />
<Route path="/docs/mods" component={Mods} />
<Route path="/docs/fast-walls" component={FastWalls} />
<Route path="/docs/privacy" component={Privacy} />
<Route path="/docs/content-policy" component={ContentPolicy} />
</Switch>
Expand Down
1 change: 1 addition & 0 deletions src/components/Docs/Sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const Sidebar = () => {
<NavGroup title="Advanced">
<NavLink to="/docs/migrating">Migrating from another editor</NavLink>
<NavLink to="/docs/mods">Mod support</NavLink>
<NavLink to="/docs/fast-walls">Fast walls</NavLink>
</NavGroup>
<NavGroup title="Legal">
<NavLink to="/docs/content-policy">Content policy</NavLink>
Expand Down
17 changes: 17 additions & 0 deletions src/components/Docs/pages/FastWalls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import Doc, {
frontMatter,
tableOfContents,
} from '../../../docs/fast-walls.mdx';

import DocPage from '../DocPage';

const Page = () => {
return (
<DocPage tableOfContents={tableOfContents()} {...frontMatter}>
<Doc />
</DocPage>
);
};

export default Page;
17 changes: 13 additions & 4 deletions src/components/SelectionInfo/SelectionInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Tooltip } from 'react-tippy';
import * as actions from '../../actions';
import { COLORS, UNIT, NOTES_VIEW } from '../../constants';
import { getMetaKeyLabel } from '../../utils';
import { getEnabledFastWalls } from '../../reducers/songs.reducer';
import { getHasCopiedNotes } from '../../reducers/clipboard.reducer';

import MiniButton from '../MiniButton';
Expand All @@ -35,17 +36,21 @@ const SelectionInfo = ({
numOfSelectedNotes,
numOfSelectedObstacles,
hasCopiedNotes,
enabledFastWalls,
deselectAll,
swapSelectedNotes,
nudgeSelection,
cutSelection,
copySelection,
pasteSelection,
toggleFastWalls,
toggleFastWallsForSelectedObstacles,
}) => {
console.log({ enabledFastWalls });
const shouldShowObstacleDurationTweaks =
numOfSelectedObstacles === 1 && numOfSelectedNotes === 0;
const shouldShowFastWallToggle = numOfSelectedObstacles > 0;

const shouldShowFastWallToggle =
enabledFastWalls && numOfSelectedObstacles > 0;

let numbers = [];
if (numOfSelectedNotes) {
Expand Down Expand Up @@ -183,7 +188,9 @@ const SelectionInfo = ({
<Spacer size={UNIT} />

{shouldShowFastWallToggle && (
<MiniButton onClick={toggleFastWalls}>Toggle Fast Walls</MiniButton>
<MiniButton onClick={toggleFastWallsForSelectedObstacles}>
Toggle Fast Walls
</MiniButton>
)}
</Wrapper>
);
Expand All @@ -206,6 +213,7 @@ const Highlight = styled.span`
const mapStateToProps = state => {
return {
hasCopiedNotes: getHasCopiedNotes(state),
enabledFastWalls: getEnabledFastWalls(state),
};
};

Expand All @@ -216,7 +224,8 @@ const mapDispatchToProps = {
cutSelection: actions.cutSelection,
copySelection: actions.copySelection,
pasteSelection: actions.pasteSelection,
toggleFastWalls: actions.toggleFastWalls,
toggleFastWallsForSelectedObstacles:
actions.toggleFastWallsForSelectedObstacles,
};

export default connect(
Expand Down
34 changes: 32 additions & 2 deletions src/components/SongDetails/SongDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,20 @@ import {
} from '../../services/file.service';
import useMount from '../../hooks/use-mount.hook';
import { sortDifficultyIds } from '../../helpers/song.helpers';
import { getSelectedSong } from '../../reducers/songs.reducer';
import {
getSelectedSong,
getEnabledFastWalls,
} from '../../reducers/songs.reducer';

import TextInput from '../TextInput';
import DropdownInput from '../DropdownInput';
import Heading from '../Heading';
import Spacer from '../Spacer';
import Spinner from '../Spinner';
import Button from '../Button';
import LabeledCheckbox from '../LabeledCheckbox';
import QuestionTooltip from '../QuestionTooltip';
import Link from '../Link';
import CoverArtPicker from '../AddSongForm/CoverArtPicker';
import SongPicker from '../AddSongForm/SongPicker';

Expand All @@ -44,7 +50,13 @@ const ENVIRONMENT_DISPLAY_MAP = {
PanicEnvironment: 'Panic',
};

const SongDetails = ({ song, stopPlaying, updateSongDetails }) => {
const SongDetails = ({
song,
stopPlaying,
enabledFastWalls,
updateSongDetails,
toggleFastWallsEnabledForSong,
}) => {
const [songData, setSongData] = React.useState(song);
const [isDirty, setIsDirty] = React.useState(false);
const [songFile, setSongFile] = React.useState(null);
Expand Down Expand Up @@ -366,6 +378,22 @@ const SongDetails = ({ song, stopPlaying, updateSongDetails }) => {
<CustomColorSettings />
<Spacer size={UNIT * 2} />
<MappingExtensionSettings />
<Spacer size={UNIT * 2} />
<LabeledCheckbox
id="enable-fast-walls"
checked={enabledFastWalls}
onChange={toggleFastWallsEnabledForSong}
>
Enable "fast walls"{' '}
<QuestionTooltip>
Allows you to customize size and shape of the grid, to place notes
outside of the typical 4×3 grid.{' '}
<Link forceAnchor to="/docs/mods#mapping-extensions">
Learn more
</Link>
.
</QuestionTooltip>
</LabeledCheckbox>
</InnerWrapper>

<Spacer size={UNIT * 36} />
Expand Down Expand Up @@ -426,12 +454,14 @@ const Center = styled.div`
const mapStateToProps = state => {
return {
song: getSelectedSong(state),
enabledFastWalls: getEnabledFastWalls(state),
};
};

const mapDispatchToProps = {
updateSongDetails: actions.updateSongDetails,
stopPlaying: actions.stopPlaying,
toggleFastWallsEnabledForSong: actions.toggleFastWallsEnabledForSong,
};

export default connect(
Expand Down
44 changes: 44 additions & 0 deletions src/docs/fast-walls.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
title: Fast Walls
subtitle: 💨
---

By default, walls pop into existence a few beats ahead of the player, and move at the same speed as the notes towards the player. Fast walls offer a way to tweak this behavior, and send walls shooting quickly towards the player.

> Fast walls are a very advanced feature, with many caveats.
>
> For one thing, you risk injuring players who are startled by how quickly an obstacle flies towards them!
>
> Additionally, they exploit a loophole in the game's programming, and will likely be patched in the future. Using fast walls might make your maps unplayable.
### Enabling fast walls

By default, you are not able to place fast walls.

Head into the "Map settings" page and scroll down to tick the "Enable Fast Walls" checkbox.

### Toggling fast walls

To set a wall as "fast", select it and then click the "Toggle Fast Walls" button in the right side-panel. Fast walls are differentiated with a large "F" in their center:

import fastWallsSrc from './images/fast-walls.png';

<img src={fastWallsSrc} width={600} />

### Working with fast walls

Simply toggling a wall as "fast" won't guarantee that it moves by the player quickly. The _speed_ of the wall depends on its _duration_ and _start beat offset_.

By default, notes and obstacles spawn 2 beats away from the player. If a note is to be struck on Beat 16, it spawns in the distance on beat 14. "Start beat offset" is a way to tweak that value; it defaults to 0, and you can push the offset back further with positive numbers; a "start beat offset" of 1 means that notes and obstacles start 3 beats away from the player instead of 2.

With a default "start beat offset" of 0, here's some rough guidelines:

- A wall that lasts for a single beat won't be very fast at all, it moves at a normal-ish speed.
- A wall that lasts 2 beats moves noticeably faster; Shortly after spawning it accelerates towards the player
- A wall that lasts 3 beats moves very very quickly, though it still has the same spawn animation as any other wall.

Fast walls are sort-of the Wild West; not many people understand them that deeply, and they're seldomly used. Some experimentation is required to get a feel for them.

They can provide neat effects in certain songs, especially when combined with [Mapping Extensions](/docs/mods#mapping-extensions) to place the walls outside of the player's personal space. But they carry risks: a future update might break any map that uses them! So please be cautious.

Better support might come in the future, but until their future feels more solid, it's not worth investing time into.
Binary file added src/docs/images/fast-walls.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/reducers/editor-entities.reducer/notes-view.reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ const obstacles = (state = initialState.obstacles, action) => {
return nudgeObstacles(direction, amount, state);
}

case 'TOGGLE_FAST_WALLS': {
case 'TOGGLE_FAST_WALLS_FOR_SELECTED_OBSTACLES': {
return state.map(obstacle => {
if (obstacle.selected) {
return {
Expand Down
21 changes: 21 additions & 0 deletions src/reducers/songs.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ interface Song {
lastOpenedAt: number;
demo?: boolean;
modSettings: ModSettings;
enabledFastWalls?: boolean;
}

interface State {
Expand Down Expand Up @@ -412,6 +413,19 @@ export default function songsReducer(state: State = initialState, action: any) {
});
}

case 'TOGGLE_FAST_WALLS_ENABLED_FOR_SONG': {
return produce(state, (draftState: State) => {
if (!state.selectedId || !draftState.byId[state.selectedId]) {
return state;
}

const song = draftState.byId[state.selectedId];

// @ts-ignore
song.enabledFastWalls = !song.enabledFastWalls;
});
}

default:
return state;
}
Expand Down Expand Up @@ -503,6 +517,13 @@ export const getEnabledMods = createSelector(
}
);

export const getEnabledFastWalls = createSelector(
getSelectedSong,
song => {
return song.enabledFastWalls;
}
);

export const getMappingMode = createSelector(
getEnabledMods,
enabledMods => {
Expand Down

0 comments on commit e2b1f62

Please sign in to comment.