s&box Package Code Search
Search C# source code, UI razor templates, shaders, and configs across s&box packages.
link Raw Facepunch API Link: https://public.facepunch.com/sbox/code/search/1/?ident=facepunch.breakout&take=20
Showing code results for query:
*
(86 total matches found)
Game
game
global using static Sandbox.Internal.GlobalGameNamespace;
global using Microsoft.AspNetCore.Components;
global using Microsoft.AspNetCore.Components.Rendering;
[assembly: global::System.Reflection.AssemblyMetadata( "AddonTitle", "Breakout" )]
[assembly: global::System.Reflection.AssemblyMetadata( "AddonIdent", "breakout" )]
[assembly: global::System.Reflection.AssemblyMetadata( "OrgIdent", "facepunch" )]
[assembly: global::System.Reflection.AssemblyMetadata( "Ident", "facepunch.breakout" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineVersion", "27" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineMinorVersion", "1" )]
[assembly: System.Runtime.Versioning.TargetFramework( ".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0" )]
[assembly: global::System.Reflection.AssemblyMetadata( "CompileTime", "2026-07-08T09:04:56.5456514Z" )]
[assembly: global::System.Reflection.AssemblyVersion("0.0.111.0")]
[assembly: global::System.Reflection.AssemblyFileVersion("0.0.111.0")]
Game
game
using System;
using Sandbox;
namespace Breakout;
/// <summary>
/// Owns purely-cosmetic game juice: the center banner, the damage flash, camera shake, brick
/// debris, wall-hit sparks, confetti and the board-clear sting. BreakoutGame delegates here and
/// re-exposes the banner/damage state for the HUD.
/// </summary>
[Title( "Game Feedback" ), Category( "Breakout" ), Icon( "auto_awesome" )]
public sealed class GameFeedback : Component
{
[Property] public GameObject DebrisPrefab { get; set; }
[Property] public GameObject WallHitPrefab { get; set; }
[Property] public GameObject ConfettiPrefab { get; set; }
[Property] public float LifeLostShake { get; set; } = 0.65f;
/// <summary>
/// Big center banner text, like "LEVEL 1" or "BOARD CLEAR!".
/// </summary>
public string BannerText { get; private set; }
/// <summary>
/// Smaller line shown beneath the banner (may be null).
/// </summary>
public string BannerSub { get; private set; }
/// <summary>
/// Ticks up each time a new banner is shown, so the HUD can restart its animation.
/// </summary>
public int BannerSeq { get; private set; }
/// <summary>
/// True while the banner should currently be visible.
/// </summary>
public bool BannerActive => !string.IsNullOrEmpty( BannerText ) && bannerSince < bannerHold;
/// <summary>
/// Ticks up each time the player takes damage, so the HUD can restart the red flash.
/// </summary>
public int DamageSeq { get; private set; }
/// <summary>
/// True while the red damage flash should currently be showing.
/// </summary>
public bool DamageActive => DamageSeq > 0 && damageSince < DamageFlashHold;
private RealTimeSince bannerSince;
private float bannerHold;
private RealTimeSince damageSince;
private const float DamageFlashHold = 0.05f;
/// <summary>
/// Shows the center banner with optional sub-text for hold seconds.
/// </summary>
public void ShowBanner( string text, string sub = null, float hold = 1.1f )
{
BannerText = text;
BannerSub = sub;
bannerSince = 0f;
bannerHold = hold;
BannerSeq++;
}
/// <summary>
/// Kicks off the red screen flash and a small camera shake when the player loses a life.
/// </summary>
public void TriggerDamageFeedback()
{
damageSince = 0f;
DamageSeq++;
ShakeCamera( LifeLostShake );
}
/// <summary>
/// Shakes the camera. Bigger amount means a stronger, longer shake.
/// </summary>
public void ShakeCamera( float amount )
{
if ( amount <= 0f )
return;
Scene.Camera.AddShake( amount * 20, amount * 10f, 0.5f );
}
/// <summary>
/// Spawns the shatter particles for a broken brick, tinted to match it.
/// </summary>
public void SpawnDebris( Block block )
{
if ( !block.IsValid() || DebrisPrefab is null )
return;
var go = DebrisPrefab.Clone( new CloneConfig( new Transform( block.WorldPosition ), startEnabled: false ) );
foreach ( var fx in go.Components.GetAll<ParticleEffect>( FindMode.EverythingInSelfAndDescendants ) )
fx.Tint = block.HealthyTint;
go.Enabled = true;
}
/// <summary>
/// Spawns a spark burst facing inward where the ball hit a wall or the paddle.
/// </summary>
public void SpawnWallHit( Vector3 worldPos, Vector3 inwardNormal )
{
if ( WallHitPrefab is null )
return;
var n = inwardNormal.Normal;
var up = MathF.Abs( n.z ) > 0.99f ? Vector3.Forward : Vector3.Up;
var rot = Rotation.LookAt( n, up );
WallHitPrefab.Clone( new CloneConfig( new Transform( worldPos, rot ), name: "wall_hit" ) );
}
/// <summary>
/// Spawns the celebratory confetti burst used on a board clear.
/// </summary>
public void SpawnConfetti( Vector3 worldPos ) => ConfettiPrefab?.Clone( worldPos );
/// <summary>
/// Plays the rising three-note chime used when a board is cleared.
/// </summary>
public void PlayClearSting()
{
float[] pitches = { 1.15f, 1.5f, 1.9f };
foreach ( var pitch in pitches )
{
var note = Sound.Play( "brick_break_01" );
if ( note is not null )
note.Pitch = pitch;
}
}
}
Game
game
@using System
@using Sandbox
@using Sandbox.UI
@namespace Breakout
@inherits Panel
@if ( Game.IsValid() && Game.State != GameState.Menu && Game.Level <= 1 )
{
<root>
<div class="container">
<span class="controls-label">CONTROLS</span>
<div class="column">
<div class="input">
@*There is no mouse/ controller move input hint so we do this.*@
@if(Input.UsingController)
{
<label class="type">Move</label><img src="ui/glyphs/xbox/leftjoystickbutton.svg" class="mouse-glyph" />
}
else
{
<label class="type">Move Paddle</label><img src="ui/glyphs/default/mouse.svg" class="mouse-glyph" />
}
</div>
<div class="input">
<label class="type">Launch</label><InputHint Action="attack1" class="key-glyph" Dark=@true />
</div>
</div>
</div>
</root>
}
@code
{
/// <summary>
/// The game this bar reads score, lives, level and mode from.
/// </summary>
[Parameter] public BreakoutGame Game { get; set; }
// Update the ui when the game state changes or when the input method changes.
protected override int BuildHash() => System.HashCode.Combine(Game?.State, Game?.Mode, Game?.Level, Input.UsingController);
}
Game
game
@using System
@using Sandbox
@using Sandbox.UI
@namespace Breakout
@inherits Panel
@*
HelpScreen is the "how to play" page you reach from the menu's HELP button. It shows a guide
of every block type and what it does. Pressing BACK runs the Back callback, which tells the
menu to show itself again.
*@
<root>
<div class="help">
<button class="back-btn" onclick=@(() => Back?.Invoke())>
<span class="back-icon">◀</span>
BACK
</button>
<div class="help-body">
<div class="help-title">HELP</div>
<div class="help-sub">Here is what each brick does when you hit it.</div>
<div class="block-grid">
@foreach ( var block in Blocks )
{
<div class="block-card">
<img class="block-icon" src="@block.Icon" />
<div class="block-info">
<div class="block-name">@block.Name</div>
<div class="block-desc">@block.Description</div>
</div>
</div>
}
</div>
</div>
</div>
</root>
@code
{
/// <summary>
/// Called when the player presses BACK, so the menu can show itself again.
/// </summary>
[Parameter] public Action Back { get; set; }
/// <summary>
/// One row in the block guide: the icon to show, the block's name, and a short description.
/// </summary>
private record BlockGuideEntry( string Icon, string Name, string Description );
// The list shown on the help page. Add a new line here to document another block type.
private static readonly BlockGuideEntry[] Blocks =
{
new( "textures/blocks/normal.png", "Brick", "Breaks in a single hit." ),
new( "textures/blocks/armoured.png", "Armoured", "Takes two hits to break." ),
new( "textures/blocks/unbreakable.png", "Unbreakable", "Can't be broken, so play around it." ),
new( "textures/blocks/explosion.png", "Explosive", "Blows up nearby bricks when it breaks." ),
new( "textures/blocks/speed.png", "Fast Ball", "Turns your ball into a faster one." ),
new( "textures/blocks/big_ball.png", "Big Ball", "Makes your ball big enough to smash armour in one hit." ),
new( "textures/blocks/fire_ball.png", "Fireball", "Turns your ball into a fireball that burns straight through bricks." ),
new( "textures/blocks/split.png", "Multi-Ball", "Drops a pickup that splits your ball into more." ),
new( "textures/blocks/expand.png", "Expand", "Drops a pickup that makes your paddle wider." ),
};
}
Game
game
$primary: red !default;
$primary-alt: white !default;
$switch-padding: 6px !default;
.coloreditor
{
flex-direction: column;
min-width: 250px;
max-width: 250px;
> .canvas
{
border-top: 1px solid rgba( white, 0.5 );
flex-grow: 1;
flex-direction: column;
padding: 10px 15px;
> textentry.textentry
{
flex-grow: 0;
flex-shrink: 0;
width: auto;
}
}
.slider
{
padding: 6.5px;
}
.slider .track
{
height: 14px;
border-radius: 14px;
left: 0px;
right: 0px;
transition: all 0.1s ease-out;
.inner
{
display: none;
}
}
.slider:hover, .slider:active
{
padding: 7px;
.track
{
height: 20px;
border-radius: 6px;
}
.thumb
{
width: 10px;
height: 16px;
margin-left: 2px;
}
}
.slider .thumb
{
width: 10px;
height: 10px;
box-shadow: 0px 0px 0px transparent;
background-color: white;
backdrop-filter: invert( 1 );
margin-left: 1px;
pointer-events: none;
}
.alpha_slider .track
{
background-image: linear-gradient( to right, rgba( #ccc, 0.05 ), rgba( #ccc, 0.9 ) );
}
.hue .track
{
background: linear-gradient(to right, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
.inner
{
display: none;
}
}
.satval
{
background: linear-gradient(to right, white, transparent);
height: 200px;
position: relative;
&:active
{
z-index: 10;
cursor: none;
}
.value_gradient
{
background: linear-gradient(to bottom, black, white);
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
mix-blend-mode: multiply;
}
.thumb
{
z-index: 10;
}
}
.presets
{
flex-wrap: wrap;
align-content: center;
justify-content: center;
padding: 15px;
border-top: 1px solid rgba( white, 0.5 );
.preset
{
background-color: white;
width: 16px;
height: 16px;
margin: 2px;
border-radius: 20px;
cursor: pointer;
&:hover
{
box-shadow: 0px 0px 1px 2px white;
}
}
}
}
.coloreditorrgba
{
flex-direction: column;
.slider
{
padding-right: 16px;
}
.slider .track
{
background-color: transparent;
height: 14px;
border-radius: 14px;
left: 0px;
right: 0px;
.inner
{
display: none;
}
}
.slider .thumb
{
width: 12px;
height: 12px;
box-shadow: 0px 0px 0px transparent;
background-color: white;
margin-left: 2px;
backdrop-filter: invert( 1 );
}
.red_slider .track
{
background-image: linear-gradient( to right, rgba( #e63439, 0.1 ), rgba( #e63439, 0.9 ) );
}
.green_slider .track
{
background-image: linear-gradient( to right, rgba( #54be35, 0.1 ), rgba( #54be35, 0.9 ) );
}
.blue_slider .track
{
background-image: linear-gradient( to right, rgba( #3472e6, 0.1 ), rgba( #3472e6, 0.9 ) );
}
.alpha_slider .track
{
background-image: linear-gradient( to right, rgba( #ccc, 0.05 ), rgba( #ccc, 0.9 ) );
}
}
.coloreditorhsva
{
flex-direction: column;
.slider
{
padding-right: 16px;
}
.slider .track
{
background-color: transparent;
height: 14px;
border-radius: 14px;
left: 0px;
right: 0px;
.inner
{
display: none;
}
}
.slider .thumb
{
width: 12px;
height: 12px;
box-shadow: 0px 0px 0px transparent;
background-color: white;
margin-left: 2px;
backdrop-filter: invert( 1 );
}
.hue_slider .track
{
background-image: linear-gradient( to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00 );
}
.alpha_slider .track
{
background-image: linear-gradient( to right, rgba( #ccc, 0.05 ), rgba( #ccc, 0.9 ) );
}
}
Game
game
menupanel
{
position: absolute;
z-index: 1000;
pointer-events: all;
font-size: 12px;
flex-shrink: 0;
.background
{
position: absolute;
left: -5000px;
right: -5000px;
top: -5000px;
bottom: -5000px;
}
> .inner
{
min-width: 200px;
min-height: 20px;
flex-direction: column;
font-family: Poppins;
font-weight: bold;
border-radius: 10px;
box-shadow: 5px 5px 30px #000e;
background-color: #2a2a2a;
flex-shrink: 0;
.spacer
{
height: 1px;
background-color: #0005;
}
.option
{
color: #fffa;
padding: 0px 8px;
cursor: pointer;
flex-shrink: 0;
height: 32px;
&:first-child
{
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}
&:last-child
{
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
.icon
{
padding: 8px;
font-family: Material Icons;
justify-content: center;
align-items: center;
flex-shrink: 0;
}
.text
{
padding: 8px;
flex-shrink: 0;
}
&:hover
{
background-color: #3472e6;
color: #f5f8fe;
}
}
}
}
Game
game
VectorControl
{
gap: 2px;
flex-grow: 1;
}
VectorControl NumberEntry
{
flex-basis: 50%;
}
Game
game
@import "/styles/_theme.scss";
$primary: $primary-blue !default;
$primary-alt: white !default;
$form-control-height: 24px !default;
.checkbox
{
cursor: pointer;
color: rgba( $primary-alt, 0.6 );
align-items: center;
gap: 8px;
label
{
pointer-events: none;
}
> .checkmark
{
padding: 1px;
font-size: 22px;
border: 1px solid $primary;
border-radius: $rounding-small;
text-align: center;
justify-content: center;
align-items: center;
color: transparent;
min-height: $form-control-height;
pointer-events: none;
flex-shrink: 0;
}
&.checked
{
> .checkmark
{
color: $primary-alt;
background-color: $primary;
}
}
&:active
{
color: $primary-alt;
}
&:hover
{
color: $primary-alt;
}
}
Game
game
using Sandbox;
namespace Breakout;
/// <summary>
/// A brick that blows up when destroyed, taking out every other breakable brick within
/// BlastRadius. Those can be exploding bricks too, so one blast can chain into more.
/// </summary>
[Title( "Exploding Block" ), Category( "Breakout" ), Icon( "bolt" )]
public sealed class ExplodingBlock : Block
{
[Property] public float BlastRadius { get; set; } = 80f;
/// <summary>
/// Breaks this brick and destroys every other breakable brick within BlastRadius, which can chain into further explosions.
/// </summary>
public override void OnDestroyed()
{
if ( Broken )
return;
var origin = WorldPosition;
base.OnDestroyed();
Game?.HitStop( 0.05f );
foreach ( var other in Scene.GetAllComponents<Block>().ToList() )
{
if ( other == this || !other.IsValid() || !other.Breakable )
continue;
if ( other.WorldPosition.Distance( origin ) <= BlastRadius )
other.OnDestroyed();
}
}
}
Game
game
namespace Breakout;
/// <summary>
/// The three ways to play. Classic is the authentic original brick wall, Arcade shuffles through
/// the custom levels, and Weekly is a shared challenge board that changes each week.
/// </summary>
public enum GameMode
{
Classic,
Arcade,
Weekly
}
Game
game
using Sandbox;
namespace Breakout;
/// <summary>
/// Base class for a timed effect living on the paddle (such as the wide-paddle boost). It runs
/// OnApply when added, then removes itself after Duration seconds, calling OnRemoved on its way out.
/// </summary>
public abstract class PaddleEffect : Component
{
[Property] public float Duration { get; set; } = 8f;
protected Paddle Paddle { get; private set; }
private TimeUntil expires;
protected override void OnStart()
{
Paddle = Components.Get<Paddle>( FindMode.EverythingInSelfAndAncestors );
if ( Paddle is null )
{
Destroy();
return;
}
expires = Duration;
OnApply();
}
protected override void OnUpdate()
{
if ( Duration > 0f && expires )
Destroy();
}
protected override void OnDestroy() => OnRemoved();
/// <summary>
/// Called once when the effect is added. Override to start the effect.
/// </summary>
protected virtual void OnApply() { }
/// <summary>
/// Called once when the effect expires or is removed. Override to undo the effect.
/// </summary>
protected virtual void OnRemoved() { }
}
Game
game
$primary: red !default;
$primary-alt: white !default;
$switch-padding: 6px !default;
.button.popupbutton.dropdown
{
cursor: pointer;
transition: all .1s ease-out;
position: relative;
> .dropdown_indicator
{
position: absolute;
right: 8px;
}
&.open
{
border-bottom-left-radius: 1px;
border-bottom-right-radius: 1px;
transition: border-radius 0.2s ease-out;
}
}
select
{
min-height: 40px;
> option
{
display: none;
}
}
Game
game
ColorControl
{
gap: 0.5rem;
flex-grow: 1;
pointer-events: all;
background-color: #000a;
border-radius: 4px;
padding: 2px;
height: 32px;
}
ColorControl TextEntry
{
flex-grow: 1;
flex-shrink: 0;
color: #aaa;
font-size: 1.2rem;
&:hover, &:focus
{
color: #ddd;
.icon
{
color: #3af;
}
}
&:active
{
color: white;
}
}
ColorControl > .colorswatch
{
aspect-ratio: 1;
border-radius: 4px;
height: 100%;
flex-shrink: 0;
cursor: pointer;
border: 2px solid #000;
}
Game
game
@import "_theme.scss";
InputHint
{
width: 28px;
height: 28px;
align-items: center;
justify-content: center;
}
.glyph
{
width: 100%;
height: 100%;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
.glyph.dark
{
filter: invert( 1 );
}
Game
game
$primary: red !default;
$primary-alt: white !default;
$switch-padding: 6px !default;
.checkbox.switch
{
cursor: pointer;
> .checkmark
{
font-size: 22px;
border: 0px solid $primary;
border-radius: 100px;
text-align: center;
justify-content: center;
align-items: center;
color: $primary-alt;
padding: $switch-padding;
padding-right: 32px;
padding-left: $switch-padding;
transition: all 0.3s ease;
background-color: rgba( $primary, 0.1 );
> .handle
{
background-color: $primary-alt;
width: 20px;
height: 20px;
border-radius: 100px;
box-shadow: 2px 2px 12px black;
}
}
&.checked
{
> .checkmark
{
background-color: $primary;
padding-left: 32px;
padding-right: $switch-padding;
}
}
&:active
{
transform: scale( 0.9 );
transform-origin: 20px 50%;
}
}
Game
game
.switchcontrol
{
flex-direction: row;
width: 100px;
min-height: 24px;
align-items: center;
cursor: pointer;
.switch-frame
{
flex-grow: 0;
flex-shrink: 1;
width: 48px;
height: 16px;
background-color: #fff1;
margin: 0px 5px;
align-items: center;
border-radius: 100px;
transition: all 0.4s linear;
.switch-inner
{
position: relative;
flex-grow: 0;
flex-shrink: 1;
background-color: #999;
width: 25px;
height: 25px;
border-radius: 100px;
left: 20%;
transform: translateX( -50% );
transition: all 0.3s ease-out;
}
}
&.active
{
.switch-frame
{
background-color: #fffa;
}
.switch-inner
{
left: 80%;
background-color: #fff;
}
}
}
Game
game
.navigator-body
{
&.hidden
{
display: none;
}
}
Game
game
ColorHueControl
{
gap: 0.5rem;
flex-grow: 1;
pointer-events: all;
background: linear-gradient( to right, red, yellow, lime, cyan, blue, magenta, red );
border-radius: 4px;
padding: 2px;
height: 12px;
position: relative;
cursor: pointer;
margin: 10px 0;
border: 1px solid #333;
&:hover
{
border: 1px solid #08f;
}
&:active
{
border: 1px solid #fff;
}
.handle
{
top: -5px;
bottom: -5px;
aspect-ratio: 1;
border-radius: 100px;
border: 2px solid #444;
position: absolute;
background-color: white;
box-shadow: 2px 2px 16px #000a;
transform: translateX( -50% );
pointer-events: none;
}
}
Game
game
.package-list
{
flex-shrink: 1;
flex-wrap: wrap;
flex-grow: 1;
h1
{
width: 100%;
margin-top: 50px;
font-size: 40px;
}
PackageCard
{
&:hover
{
sound-in: "ui.button.over";
}
}
VirtualGrid
{
width: 100%;
height: 100%;
.cell
{
}
}
}
Game
game
using Sandbox;
namespace Breakout;
/// <summary>
/// Maps level symbols to the colors used when drawing a level's thumbnail preview. This is only for
/// the editor preview image; the in-game bricks get their color from the spawner's palette.
/// </summary>
public static class BlockPalette
{
public static readonly Color Background = new( 0.07f, 0.08f, 0.10f );
public static readonly Color Empty = new( 0.16f, 0.17f, 0.19f );
/// <summary>
/// The preview color for a level symbol (falls back to the empty-cell color for unknown symbols).
/// </summary>
public static Color ColorFor( char symbol )
{
return symbol switch
{
'1' => new Color( 0.95f, 0.62f, 0.20f ), // normal
'2' => new Color( 0.36f, 0.55f, 0.78f ), // multi-hit
'P' => new Color( 0.35f, 0.78f, 0.42f ), // power-up (multi-ball)
'E' => new Color( 0.30f, 0.78f, 0.80f ), // expand
'X' => new Color( 0.86f, 0.27f, 0.27f ), // exploding
'#' => new Color( 0.55f, 0.55f, 0.58f ), // unbreakable
'S' => new Color( 1.00f, 0.45f, 0.20f ), // fast ball
'B' => new Color( 0.40f, 0.70f, 1.00f ), // big ball
'F' => new Color( 1.00f, 0.35f, 0.10f ), // fireball
_ => Empty,
};
}
}
Debug: View Raw JSON Response
{
"TotalCount": 86,
"Files": [
{
"Ident": "facepunch.breakout",
"Path": ".obj/__compiler_extra.cs",
"FileName": "__compiler_extra.cs",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "global using static Sandbox.Internal.GlobalGameNamespace;\r\nglobal using Microsoft.AspNetCore.Components;\r\nglobal using Microsoft.AspNetCore.Components.Rendering;\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"AddonTitle\", \"Breakout\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"AddonIdent\", \"breakout\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"OrgIdent\", \"facepunch\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"Ident\", \"facepunch.breakout\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"EngineVersion\", \"27\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"EngineMinorVersion\", \"1\" )]\r\n\r\n[assembly: System.Runtime.Versioning.TargetFramework( \".NETCoreApp,Version=v9.0\", FrameworkDisplayName = \".NET 9.0\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"CompileTime\", \"2026-07-08T09:04:56.5456514Z\" )]\r\n[assembly: global::System.Reflection.AssemblyVersion(\"0.0.111.0\")]\r\n[assembly: global::System.Reflection.AssemblyFileVersion(\"0.0.111.0\")]"
},
{
"Ident": "facepunch.breakout",
"Path": "Game/GameFeedback.cs",
"FileName": "GameFeedback.cs",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "using System;\r\nusing Sandbox;\r\n\r\nnamespace Breakout;\r\n\r\n/// <summary>\r\n/// Owns purely-cosmetic game juice: the center banner, the damage flash, camera shake, brick\r\n/// debris, wall-hit sparks, confetti and the board-clear sting. BreakoutGame delegates here and\r\n/// re-exposes the banner/damage state for the HUD.\r\n/// </summary>\r\n[Title( \"Game Feedback\" ), Category( \"Breakout\" ), Icon( \"auto_awesome\" )]\r\npublic sealed class GameFeedback : Component\r\n{\r\n\t[Property] public GameObject DebrisPrefab { get; set; }\r\n\t[Property] public GameObject WallHitPrefab { get; set; }\r\n\t[Property] public GameObject ConfettiPrefab { get; set; }\r\n\t[Property] public float LifeLostShake { get; set; } = 0.65f;\r\n\r\n\t/// <summary>\r\n\t/// Big center banner text, like \"LEVEL 1\" or \"BOARD CLEAR!\".\r\n\t/// </summary>\r\n\tpublic string BannerText { get; private set; }\r\n\r\n\t/// <summary>\r\n\t/// Smaller line shown beneath the banner (may be null).\r\n\t/// </summary>\r\n\tpublic string BannerSub { get; private set; }\r\n\r\n\t/// <summary>\r\n\t/// Ticks up each time a new banner is shown, so the HUD can restart its animation.\r\n\t/// </summary>\r\n\tpublic int BannerSeq { get; private set; }\r\n\r\n\t/// <summary>\r\n\t/// True while the banner should currently be visible.\r\n\t/// </summary>\r\n\tpublic bool BannerActive => !string.IsNullOrEmpty( BannerText ) && bannerSince < bannerHold;\r\n\r\n\t/// <summary>\r\n\t/// Ticks up each time the player takes damage, so the HUD can restart the red flash.\r\n\t/// </summary>\r\n\tpublic int DamageSeq { get; private set; }\r\n\r\n\t/// <summary>\r\n\t/// True while the red damage flash should currently be showing.\r\n\t/// </summary>\r\n\tpublic bool DamageActive => DamageSeq > 0 && damageSince < DamageFlashHold;\r\n\r\n\tprivate RealTimeSince bannerSince;\r\n\tprivate float bannerHold;\r\n\tprivate RealTimeSince damageSince;\r\n\tprivate const float DamageFlashHold = 0.05f;\r\n\r\n\t/// <summary>\r\n\t/// Shows the center banner with optional sub-text for hold seconds.\r\n\t/// </summary>\r\n\tpublic void ShowBanner( string text, string sub = null, float hold = 1.1f )\r\n\t{\r\n\t\tBannerText = text;\r\n\t\tBannerSub = sub;\r\n\t\tbannerSince = 0f;\r\n\t\tbannerHold = hold;\r\n\t\tBannerSeq++;\r\n\t}\r\n\r\n\t/// <summary>\r\n\t/// Kicks off the red screen flash and a small camera shake when the player loses a life.\r\n\t/// </summary>\r\n\tpublic void TriggerDamageFeedback()\r\n\t{\r\n\t\tdamageSince = 0f;\r\n\t\tDamageSeq++;\r\n\t\tShakeCamera( LifeLostShake );\r\n\t}\r\n\r\n\t/// <summary>\r\n\t/// Shakes the camera. Bigger amount means a stronger, longer shake.\r\n\t/// </summary>\r\n\tpublic void ShakeCamera( float amount )\r\n\t{\r\n\t\tif ( amount <= 0f )\r\n\t\t\treturn;\r\n\r\n\t\tScene.Camera.AddShake( amount * 20, amount * 10f, 0.5f );\r\n\t}\r\n\r\n\t/// <summary>\r\n\t/// Spawns the shatter particles for a broken brick, tinted to match it.\r\n\t/// </summary>\r\n\tpublic void SpawnDebris( Block block )\r\n\t{\r\n\t\tif ( !block.IsValid() || DebrisPrefab is null )\r\n\t\t\treturn;\r\n\r\n\t\tvar go = DebrisPrefab.Clone( new CloneConfig( new Transform( block.WorldPosition ), startEnabled: false ) );\r\n\r\n\t\tforeach ( var fx in go.Components.GetAll<ParticleEffect>( FindMode.EverythingInSelfAndDescendants ) )\r\n\t\t\tfx.Tint = block.HealthyTint;\r\n\r\n\t\tgo.Enabled = true;\r\n\t}\r\n\r\n\t/// <summary>\r\n\t/// Spawns a spark burst facing inward where the ball hit a wall or the paddle.\r\n\t/// </summary>\r\n\tpublic void SpawnWallHit( Vector3 worldPos, Vector3 inwardNormal )\r\n\t{\r\n\t\tif ( WallHitPrefab is null )\r\n\t\t\treturn;\r\n\r\n\t\tvar n = inwardNormal.Normal;\r\n\t\tvar up = MathF.Abs( n.z ) > 0.99f ? Vector3.Forward : Vector3.Up;\r\n\t\tvar rot = Rotation.LookAt( n, up );\r\n\t\tWallHitPrefab.Clone( new CloneConfig( new Transform( worldPos, rot ), name: \"wall_hit\" ) );\r\n\t}\r\n\r\n\t/// <summary>\r\n\t/// Spawns the celebratory confetti burst used on a board clear.\r\n\t/// </summary>\r\n\tpublic void SpawnConfetti( Vector3 worldPos ) => ConfettiPrefab?.Clone( worldPos );\r\n\r\n\t/// <summary>\r\n\t/// Plays the rising three-note chime used when a board is cleared.\r\n\t/// </summary>\r\n\tpublic void PlayClearSting()\r\n\t{\r\n\t\tfloat[] pitches = { 1.15f, 1.5f, 1.9f };\r\n\t\tforeach ( var pitch in pitches )\r\n\t\t{\r\n\t\t\tvar note = Sound.Play( \"brick_break_01\" );\r\n\t\t\tif ( note is not null )\r\n\t\t\t\tnote.Pitch = pitch;\r\n\t\t}\r\n\t}\r\n}\r\n"
},
{
"Ident": "facepunch.breakout",
"Path": "UI/Controls.razor",
"FileName": "Controls.razor",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "@using System\r\n@using Sandbox\r\n@using Sandbox.UI\r\n@namespace Breakout\r\n@inherits Panel\r\n\r\n@if ( Game.IsValid() && Game.State != GameState.Menu && Game.Level <= 1 )\r\n{\r\n <root>\r\n <div class=\"container\">\r\n <span class=\"controls-label\">CONTROLS</span>\r\n <div class=\"column\">\r\n <div class=\"input\">\r\n @*There is no mouse/ controller move input hint so we do this.*@\r\n @if(Input.UsingController)\r\n {\r\n <label class=\"type\">Move</label><img src=\"ui/glyphs/xbox/leftjoystickbutton.svg\" class=\"mouse-glyph\" />\r\n }\r\n else\r\n {\r\n <label class=\"type\">Move Paddle</label><img src=\"ui/glyphs/default/mouse.svg\" class=\"mouse-glyph\" />\r\n }\r\n </div>\r\n <div class=\"input\">\r\n <label class=\"type\">Launch</label><InputHint Action=\"attack1\" class=\"key-glyph\" Dark=@true />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n </root>\r\n}\r\n\r\n@code\r\n{\r\n /// <summary>\r\n /// The game this bar reads score, lives, level and mode from.\r\n /// </summary>\r\n [Parameter] public BreakoutGame Game { get; set; }\r\n\r\n // Update the ui when the game state changes or when the input method changes.\r\n protected override int BuildHash() => System.HashCode.Combine(Game?.State, Game?.Mode, Game?.Level, Input.UsingController);\r\n}\r\n"
},
{
"Ident": "facepunch.breakout",
"Path": "UI/HelpScreen.razor",
"FileName": "HelpScreen.razor",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "@using System\r\n@using Sandbox\r\n@using Sandbox.UI\r\n@namespace Breakout\r\n@inherits Panel\r\n\r\n@*\r\n HelpScreen is the \"how to play\" page you reach from the menu's HELP button. It shows a guide\r\n of every block type and what it does. Pressing BACK runs the Back callback, which tells the\r\n menu to show itself again.\r\n*@\r\n\r\n<root>\r\n <div class=\"help\">\r\n <button class=\"back-btn\" onclick=@(() => Back?.Invoke())>\r\n <span class=\"back-icon\">\u25c0</span>\r\n BACK\r\n </button>\r\n\r\n <div class=\"help-body\">\r\n <div class=\"help-title\">HELP</div>\r\n <div class=\"help-sub\">Here is what each brick does when you hit it.</div>\r\n\r\n <div class=\"block-grid\">\r\n @foreach ( var block in Blocks )\r\n {\r\n <div class=\"block-card\">\r\n <img class=\"block-icon\" src=\"@block.Icon\" />\r\n <div class=\"block-info\">\r\n <div class=\"block-name\">@block.Name</div>\r\n <div class=\"block-desc\">@block.Description</div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</root>\r\n\r\n@code\r\n{\r\n /// <summary>\r\n /// Called when the player presses BACK, so the menu can show itself again.\r\n /// </summary>\r\n [Parameter] public Action Back { get; set; }\r\n\r\n /// <summary>\r\n /// One row in the block guide: the icon to show, the block's name, and a short description.\r\n /// </summary>\r\n private record BlockGuideEntry( string Icon, string Name, string Description );\r\n\r\n // The list shown on the help page. Add a new line here to document another block type.\r\n private static readonly BlockGuideEntry[] Blocks =\r\n {\r\n new( \"textures/blocks/normal.png\", \"Brick\", \"Breaks in a single hit.\" ),\r\n new( \"textures/blocks/armoured.png\", \"Armoured\", \"Takes two hits to break.\" ),\r\n new( \"textures/blocks/unbreakable.png\", \"Unbreakable\", \"Can't be broken, so play around it.\" ),\r\n new( \"textures/blocks/explosion.png\", \"Explosive\", \"Blows up nearby bricks when it breaks.\" ),\r\n new( \"textures/blocks/speed.png\", \"Fast Ball\", \"Turns your ball into a faster one.\" ),\r\n new( \"textures/blocks/big_ball.png\", \"Big Ball\", \"Makes your ball big enough to smash armour in one hit.\" ),\r\n new( \"textures/blocks/fire_ball.png\", \"Fireball\", \"Turns your ball into a fireball that burns straight through bricks.\" ),\r\n new( \"textures/blocks/split.png\", \"Multi-Ball\", \"Drops a pickup that splits your ball into more.\" ),\r\n new( \"textures/blocks/expand.png\", \"Expand\", \"Drops a pickup that makes your paddle wider.\" ),\r\n };\r\n}\r\n"
},
{
"Ident": "facepunch.breakout",
"Path": "styles/form/_coloreditor.scss",
"FileName": "_coloreditor.scss",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "\r\n$primary: red !default;\r\n$primary-alt: white !default;\r\n\r\n$switch-padding: 6px !default;\r\n\r\n.coloreditor\r\n{\r\n\tflex-direction: column;\r\n\tmin-width: 250px;\r\n\tmax-width: 250px;\r\n\r\n\t> .canvas\r\n\t{\r\n\t\tborder-top: 1px solid rgba( white, 0.5 );\r\n\t\tflex-grow: 1;\r\n\t\tflex-direction: column;\r\n\t\tpadding: 10px 15px;\r\n\r\n\r\n\t\t> textentry.textentry\r\n\t\t{\r\n\t\t\tflex-grow: 0;\r\n\t\t\tflex-shrink: 0;\r\n\t\t\twidth: auto;\r\n\t\t}\r\n\t}\r\n\r\n\t.slider\r\n\t{\r\n\t\tpadding: 6.5px;\r\n\t}\r\n\r\n\t.slider .track\r\n\t{\r\n\t\theight: 14px;\r\n\t\tborder-radius: 14px;\r\n\t\tleft: 0px;\r\n\t\tright: 0px;\r\n\t\ttransition: all 0.1s ease-out;\r\n\r\n\t\t.inner\r\n\t\t{\r\n\t\t\tdisplay: none;\r\n\t\t}\r\n\t}\r\n\r\n\t.slider:hover, .slider:active\r\n\t{\r\n\t\tpadding: 7px;\r\n\r\n\t\t.track\r\n\t\t{\r\n\t\t\theight: 20px;\r\n\t\t\tborder-radius: 6px;\r\n\t\t}\r\n\r\n\t\t.thumb\r\n\t\t{\r\n\t\t\twidth: 10px;\r\n\t\t\theight: 16px;\r\n\t\t\tmargin-left: 2px;\r\n\t\t}\r\n\t}\r\n\r\n\t.slider .thumb\r\n\t{\r\n\t\twidth: 10px;\r\n\t\theight: 10px;\r\n\t\tbox-shadow: 0px 0px 0px transparent;\r\n\t\tbackground-color: white;\r\n\t\tbackdrop-filter: invert( 1 );\r\n\t\tmargin-left: 1px;\r\n\t\tpointer-events: none;\r\n\t}\r\n\r\n\t.alpha_slider .track\r\n\t{\r\n\t\tbackground-image: linear-gradient( to right, rgba( #ccc, 0.05 ), rgba( #ccc, 0.9 ) );\r\n\t}\r\n\r\n\t.hue .track\r\n\t{\r\n\t\tbackground: linear-gradient(to right, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\r\n\r\n\t\t.inner\r\n\t\t{\r\n\t\t\tdisplay: none;\r\n\t\t}\r\n\t}\r\n\r\n\t.satval\r\n\t{\r\n\t\tbackground: linear-gradient(to right, white, transparent);\r\n\t\theight: 200px;\r\n\t\tposition: relative;\r\n\r\n\t\t&:active\r\n\t\t{\r\n\t\t\tz-index: 10;\r\n\t\t\tcursor: none;\r\n\t\t}\r\n\r\n\t\t.value_gradient\r\n\t\t{\r\n\t\t\tbackground: linear-gradient(to bottom, black, white);\r\n\t\t\tposition: absolute;\r\n\t\t\ttop: 0;\r\n\t\t\tleft: 0;\r\n\t\t\tright: 0;\r\n\t\t\tbottom: 0;\r\n\t\t\tpointer-events: none;\r\n\t\t\tmix-blend-mode: multiply;\r\n\t\t}\r\n\r\n\t\t.thumb\r\n\t\t{\r\n\t\t\tz-index: 10;\r\n\t\t}\r\n\t}\r\n\r\n\t.presets\r\n\t{\r\n\t\tflex-wrap: wrap;\r\n\t\talign-content: center;\r\n\t\tjustify-content: center;\r\n\t\tpadding: 15px;\r\n\t\tborder-top: 1px solid rgba( white, 0.5 );\r\n\r\n\t\t.preset\r\n\t\t{\r\n\t\t\tbackground-color: white;\r\n\t\t\twidth: 16px;\r\n\t\t\theight: 16px;\r\n\t\t\tmargin: 2px;\r\n\t\t\tborder-radius: 20px;\r\n\t\t\tcursor: pointer;\r\n\t\t\t\r\n\t\t\t&:hover\r\n\t\t\t{\r\n\t\t\t\tbox-shadow: 0px 0px 1px 2px white;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n.coloreditorrgba\r\n{\r\n\tflex-direction: column;\r\n\r\n\t.slider\r\n\t{\r\n\t\tpadding-right: 16px;\r\n\t}\r\n\r\n\t.slider .track\r\n\t{\r\n\t\tbackground-color: transparent;\r\n\t\theight: 14px;\r\n\t\tborder-radius: 14px;\r\n\t\tleft: 0px;\r\n\t\tright: 0px;\r\n\r\n\t\t.inner\r\n\t\t{\r\n\t\t\tdisplay: none;\r\n\t\t}\r\n\t}\r\n\r\n\t.slider .thumb\r\n\t{\r\n\t\twidth: 12px;\r\n\t\theight: 12px;\r\n\t\tbox-shadow: 0px 0px 0px transparent;\r\n\t\tbackground-color: white;\r\n\t\tmargin-left: 2px;\r\n\t\tbackdrop-filter: invert( 1 );\r\n\t}\r\n\r\n\t.red_slider .track\r\n\t{\r\n\t\tbackground-image: linear-gradient( to right, rgba( #e63439, 0.1 ), rgba( #e63439, 0.9 ) );\r\n\t}\r\n\r\n\t.green_slider .track\r\n\t{\r\n\t\tbackground-image: linear-gradient( to right, rgba( #54be35, 0.1 ), rgba( #54be35, 0.9 ) );\r\n\t}\r\n\r\n\t.blue_slider .track\r\n\t{\r\n\t\tbackground-image: linear-gradient( to right, rgba( #3472e6, 0.1 ), rgba( #3472e6, 0.9 ) );\r\n\t}\r\n\r\n\t.alpha_slider .track\r\n\t{\r\n\t\tbackground-image: linear-gradient( to right, rgba( #ccc, 0.05 ), rgba( #ccc, 0.9 ) );\r\n\t}\r\n}\r\n\r\n\r\n.coloreditorhsva\r\n{\r\n\tflex-direction: column;\r\n\r\n\t.slider\r\n\t{\r\n\t\tpadding-right: 16px;\r\n\t}\r\n\r\n\t.slider .track\r\n\t{\r\n\t\tbackground-color: transparent;\r\n\t\theight: 14px;\r\n\t\tborder-radius: 14px;\r\n\t\tleft: 0px;\r\n\t\tright: 0px;\r\n\r\n\t\t.inner\r\n\t\t{\r\n\t\t\tdisplay: none;\r\n\t\t}\r\n\t}\r\n\r\n\t.slider .thumb\r\n\t{\r\n\t\twidth: 12px;\r\n\t\theight: 12px;\r\n\t\tbox-shadow: 0px 0px 0px transparent;\r\n\t\tbackground-color: white;\r\n\t\tmargin-left: 2px;\r\n\t\tbackdrop-filter: invert( 1 );\r\n\t}\r\n\t\t\r\n\t.hue_slider .track\r\n\t{\r\n\t\tbackground-image: linear-gradient( to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00 );\r\n\t}\r\n\r\n\t.alpha_slider .track\r\n\t{\r\n\t\tbackground-image: linear-gradient( to right, rgba( #ccc, 0.05 ), rgba( #ccc, 0.9 ) );\r\n\t}\r\n}"
},
{
"Ident": "facepunch.breakout",
"Path": "ui/menupanel.razor.scss",
"FileName": "menupanel.razor.scss",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "\r\nmenupanel\r\n{\r\n position: absolute;\r\n z-index: 1000;\r\n pointer-events: all;\r\n font-size: 12px;\r\n flex-shrink: 0;\r\n\r\n .background\r\n {\r\n position: absolute;\r\n left: -5000px;\r\n right: -5000px;\r\n top: -5000px;\r\n bottom: -5000px;\r\n }\r\n\r\n > .inner\r\n {\r\n min-width: 200px;\r\n min-height: 20px;\r\n flex-direction: column;\r\n font-family: Poppins;\r\n font-weight: bold;\r\n border-radius: 10px;\r\n box-shadow: 5px 5px 30px #000e;\r\n background-color: #2a2a2a;\r\n flex-shrink: 0;\r\n\r\n .spacer\r\n {\r\n height: 1px;\r\n background-color: #0005;\r\n }\r\n\r\n .option\r\n {\r\n color: #fffa;\r\n padding: 0px 8px;\r\n cursor: pointer;\r\n flex-shrink: 0;\r\n height: 32px;\r\n\r\n &:first-child\r\n {\r\n border-top-left-radius: 10px;\r\n border-top-right-radius: 10px;\r\n }\r\n\r\n &:last-child\r\n {\r\n border-bottom-left-radius: 10px;\r\n border-bottom-right-radius: 10px;\r\n }\r\n\r\n .icon\r\n {\r\n padding: 8px;\r\n font-family: Material Icons;\r\n justify-content: center;\r\n align-items: center;\r\n flex-shrink: 0;\r\n }\r\n\r\n .text\r\n {\r\n padding: 8px;\r\n flex-shrink: 0;\r\n }\r\n\r\n &:hover\r\n {\r\n background-color: #3472e6;\r\n color: #f5f8fe;\r\n }\r\n }\r\n }\r\n}\r\n"
},
{
"Ident": "facepunch.breakout",
"Path": "ui/controls/vectorcontrol.cs.scss",
"FileName": "vectorcontrol.cs.scss",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "VectorControl\r\n{\r\n\tgap: 2px;\r\n\tflex-grow: 1;\r\n}\r\n\r\nVectorControl NumberEntry\r\n{\r\n\tflex-basis: 50%;\r\n}"
},
{
"Ident": "facepunch.breakout",
"Path": "styles/form/_checkbox.scss",
"FileName": "_checkbox.scss",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "\r\n@import \"/styles/_theme.scss\";\r\n\r\n$primary: $primary-blue !default;\r\n$primary-alt: white !default;\r\n$form-control-height: 24px !default;\r\n\r\n.checkbox\r\n{\r\n\tcursor: pointer;\r\n\tcolor: rgba( $primary-alt, 0.6 );\r\n\talign-items: center;\r\n\tgap: 8px;\r\n\r\n\tlabel\r\n\t{\r\n\t\tpointer-events: none;\r\n\t}\r\n\r\n\t> .checkmark\r\n\t{\r\n\t\tpadding: 1px;\r\n\t\tfont-size: 22px;\r\n\t\tborder: 1px solid $primary;\r\n\t\tborder-radius: $rounding-small;\r\n\t\ttext-align: center;\r\n\t\tjustify-content: center;\r\n\t\talign-items: center;\r\n\t\tcolor: transparent;\r\n\t\tmin-height: $form-control-height;\r\n\t\tpointer-events: none;\r\n\t\tflex-shrink: 0;\r\n\t}\r\n\r\n\t&.checked\r\n\t{\r\n\t\t> .checkmark\r\n\t\t{\r\n\t\t\tcolor: $primary-alt;\r\n\t\t\tbackground-color: $primary;\r\n\t\t}\r\n\t}\r\n\r\n\t&:active\r\n\t{\r\n\t\tcolor: $primary-alt;\r\n\t}\r\n\r\n\t&:hover\r\n\t{\r\n\t\tcolor: $primary-alt;\r\n\t}\r\n}\r\n"
},
{
"Ident": "facepunch.breakout",
"Path": "Blocks/ExplodingBlock.cs",
"FileName": "ExplodingBlock.cs",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "using Sandbox;\r\n\r\nnamespace Breakout;\r\n\r\n/// <summary>\r\n/// A brick that blows up when destroyed, taking out every other breakable brick within\r\n/// BlastRadius. Those can be exploding bricks too, so one blast can chain into more.\r\n/// </summary>\r\n[Title( \"Exploding Block\" ), Category( \"Breakout\" ), Icon( \"bolt\" )]\r\npublic sealed class ExplodingBlock : Block\r\n{\r\n\t[Property] public float BlastRadius { get; set; } = 80f;\r\n\r\n\t/// <summary>\r\n\t/// Breaks this brick and destroys every other breakable brick within BlastRadius, which can chain into further explosions.\r\n\t/// </summary>\r\n\tpublic override void OnDestroyed()\r\n\t{\r\n\t\tif ( Broken )\r\n\t\t\treturn;\r\n\r\n\t\tvar origin = WorldPosition;\r\n\r\n\t\tbase.OnDestroyed();\r\n\t\tGame?.HitStop( 0.05f );\r\n\r\n\t\tforeach ( var other in Scene.GetAllComponents<Block>().ToList() )\r\n\t\t{\r\n\t\t\tif ( other == this || !other.IsValid() || !other.Breakable )\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tif ( other.WorldPosition.Distance( origin ) <= BlastRadius )\r\n\t\t\t\tother.OnDestroyed();\r\n\t\t}\r\n\t}\r\n}\r\n"
},
{
"Ident": "facepunch.breakout",
"Path": "Game/GameMode.cs",
"FileName": "GameMode.cs",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "namespace Breakout;\r\n\r\n/// <summary>\r\n/// The three ways to play. Classic is the authentic original brick wall, Arcade shuffles through\r\n/// the custom levels, and Weekly is a shared challenge board that changes each week.\r\n/// </summary>\r\npublic enum GameMode\r\n{\r\n\tClassic,\r\n\tArcade,\r\n\tWeekly\r\n}\r\n"
},
{
"Ident": "facepunch.breakout",
"Path": "Paddle/PaddleEffect.cs",
"FileName": "PaddleEffect.cs",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "using Sandbox;\r\n\r\nnamespace Breakout;\r\n\r\n/// <summary>\r\n/// Base class for a timed effect living on the paddle (such as the wide-paddle boost). It runs\r\n/// OnApply when added, then removes itself after Duration seconds, calling OnRemoved on its way out.\r\n/// </summary>\r\npublic abstract class PaddleEffect : Component\r\n{\r\n\t[Property] public float Duration { get; set; } = 8f;\r\n\r\n\tprotected Paddle Paddle { get; private set; }\r\n\r\n\tprivate TimeUntil expires;\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tPaddle = Components.Get<Paddle>( FindMode.EverythingInSelfAndAncestors );\r\n\t\tif ( Paddle is null )\r\n\t\t{\r\n\t\t\tDestroy();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\texpires = Duration;\r\n\t\tOnApply();\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tif ( Duration > 0f && expires )\r\n\t\t\tDestroy();\r\n\t}\r\n\r\n\tprotected override void OnDestroy() => OnRemoved();\r\n\r\n\t/// <summary>\r\n\t/// Called once when the effect is added. Override to start the effect.\r\n\t/// </summary>\r\n\tprotected virtual void OnApply() { }\r\n\r\n\t/// <summary>\r\n\t/// Called once when the effect expires or is removed. Override to undo the effect.\r\n\t/// </summary>\r\n\tprotected virtual void OnRemoved() { }\r\n}\r\n"
},
{
"Ident": "facepunch.breakout",
"Path": "styles/form/_dropdown.scss",
"FileName": "_dropdown.scss",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "\r\n$primary: red !default;\r\n$primary-alt: white !default;\r\n\r\n$switch-padding: 6px !default;\r\n\r\n.button.popupbutton.dropdown\r\n{\r\n\tcursor: pointer;\r\n\ttransition: all .1s ease-out;\r\n\tposition: relative;\r\n\r\n\t> .dropdown_indicator\r\n\t{\r\n\t\tposition: absolute;\r\n\t\tright: 8px;\r\n\t}\r\n\r\n\t&.open\r\n\t{\r\n\t\tborder-bottom-left-radius: 1px;\r\n\t\tborder-bottom-right-radius: 1px;\r\n\t\ttransition: border-radius 0.2s ease-out;\r\n\t}\r\n}\r\n\r\nselect\r\n{\r\n\tmin-height: 40px;\r\n\r\n\t> option\r\n\t{\r\n\t\tdisplay: none;\r\n\t}\r\n}"
},
{
"Ident": "facepunch.breakout",
"Path": "ui/controls/color/colorcontrol.cs.scss",
"FileName": "colorcontrol.cs.scss",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "ColorControl\r\n{\r\n\tgap: 0.5rem;\r\n\tflex-grow: 1;\r\n\tpointer-events: all;\r\n\tbackground-color: #000a;\r\n\tborder-radius: 4px;\r\n\tpadding: 2px;\r\n\theight: 32px;\r\n}\r\n\r\nColorControl TextEntry\r\n{\r\n\tflex-grow: 1;\r\n\tflex-shrink: 0;\r\n\tcolor: #aaa;\r\n\tfont-size: 1.2rem;\r\n\r\n\t&:hover, &:focus\r\n\t{\r\n\t\tcolor: #ddd;\r\n\r\n\t\t.icon\r\n\t\t{\r\n\t\t\tcolor: #3af;\r\n\t\t}\r\n\t}\r\n\r\n\t&:active\r\n\t{\r\n\t\tcolor: white;\r\n\t}\r\n}\r\n\r\nColorControl > .colorswatch\r\n{\r\n\taspect-ratio: 1;\r\n\tborder-radius: 4px;\r\n\theight: 100%;\r\n\tflex-shrink: 0;\r\n\tcursor: pointer;\r\n\tborder: 2px solid #000;\r\n}"
},
{
"Ident": "facepunch.breakout",
"Path": "ui/inputhint.razor.scss",
"FileName": "inputhint.razor.scss",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "@import \"_theme.scss\";\r\n\r\nInputHint\r\n{\r\n\twidth: 28px;\r\n\theight: 28px;\r\n\talign-items: center;\r\n\tjustify-content: center;\r\n}\r\n\r\n.glyph\r\n{\r\n\twidth: 100%;\r\n\theight: 100%;\r\n\tbackground-size: contain;\r\n\tbackground-position: center;\r\n\tbackground-repeat: no-repeat;\r\n\r\n}\r\n\r\n.glyph.dark\r\n{\r\n\tfilter: invert( 1 );\r\n}\r\n"
},
{
"Ident": "facepunch.breakout",
"Path": "styles/form/_switch.scss",
"FileName": "_switch.scss",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "\r\n$primary: red !default;\r\n$primary-alt: white !default;\r\n\r\n$switch-padding: 6px !default;\r\n\r\n.checkbox.switch\r\n{\r\n\tcursor: pointer;\r\n\r\n\t> .checkmark\r\n\t{\r\n\t\tfont-size: 22px;\r\n\t\tborder: 0px solid $primary;\r\n\t\tborder-radius: 100px;\r\n\t\ttext-align: center;\r\n\t\tjustify-content: center;\r\n\t\talign-items: center;\r\n\t\tcolor: $primary-alt;\r\n\t\tpadding: $switch-padding;\r\n\t\tpadding-right: 32px;\r\n\t\tpadding-left: $switch-padding;\r\n\t\ttransition: all 0.3s ease;\r\n\t\tbackground-color: rgba( $primary, 0.1 );\r\n\r\n\t\t> .handle\r\n\t\t{\r\n\t\t\tbackground-color: $primary-alt;\r\n\t\t\twidth: 20px;\r\n\t\t\theight: 20px;\r\n\t\t\tborder-radius: 100px;\r\n\t\t\tbox-shadow: 2px 2px 12px black;\r\n\t\t}\r\n\t}\r\n\r\n\t&.checked\r\n\t{\r\n\t\t> .checkmark\r\n\t\t{\r\n\t\t\tbackground-color: $primary;\r\n\t\t\tpadding-left: 32px;\r\n\t\t\tpadding-right: $switch-padding;\r\n\t\t}\r\n\t}\r\n\r\n\t&:active\r\n\t{\r\n\t\ttransform: scale( 0.9 );\r\n\t\ttransform-origin: 20px 50%;\r\n\t}\r\n}\r\n"
},
{
"Ident": "facepunch.breakout",
"Path": "ui/controls/switchcontrol.razor.scss",
"FileName": "switchcontrol.razor.scss",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "\r\n.switchcontrol\r\n{\r\n flex-direction: row;\r\n width: 100px;\r\n min-height: 24px;\r\n align-items: center;\r\n cursor: pointer;\r\n\r\n .switch-frame\r\n {\r\n flex-grow: 0;\r\n flex-shrink: 1;\r\n width: 48px;\r\n height: 16px;\r\n background-color: #fff1;\r\n margin: 0px 5px;\r\n align-items: center;\r\n border-radius: 100px;\r\n transition: all 0.4s linear;\r\n\r\n .switch-inner\r\n {\r\n position: relative;\r\n flex-grow: 0;\r\n flex-shrink: 1;\r\n background-color: #999;\r\n width: 25px;\r\n height: 25px;\r\n border-radius: 100px;\r\n left: 20%;\r\n transform: translateX( -50% );\r\n transition: all 0.3s ease-out;\r\n }\r\n }\r\n\r\n &.active\r\n {\r\n .switch-frame\r\n {\r\n background-color: #fffa;\r\n }\r\n\r\n .switch-inner\r\n {\r\n left: 80%;\r\n background-color: #fff;\r\n }\r\n }\r\n}\r\n"
},
{
"Ident": "facepunch.breakout",
"Path": "styles/base/_navigator.scss",
"FileName": "_navigator.scss",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": ".navigator-body\r\n{\r\n\t&.hidden\r\n\t{\r\n\t\tdisplay: none;\r\n\t}\r\n}\r\n"
},
{
"Ident": "facepunch.breakout",
"Path": "ui/controls/color/colorhuecontrol.cs.scss",
"FileName": "colorhuecontrol.cs.scss",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "ColorHueControl\r\n{\r\n\tgap: 0.5rem;\r\n\tflex-grow: 1;\r\n\tpointer-events: all;\r\n\tbackground: linear-gradient( to right, red, yellow, lime, cyan, blue, magenta, red );\r\n\tborder-radius: 4px;\r\n\tpadding: 2px;\r\n\theight: 12px;\r\n\tposition: relative;\r\n\tcursor: pointer;\r\n\tmargin: 10px 0;\r\n\tborder: 1px solid #333;\r\n\r\n\t&:hover\r\n\t{\r\n\t\tborder: 1px solid #08f;\r\n\t}\r\n\r\n\t&:active\r\n\t{\r\n\t\tborder: 1px solid #fff;\r\n\t}\r\n\r\n\t.handle\r\n\t{\r\n\t\ttop: -5px;\r\n\t\tbottom: -5px;\r\n\t\taspect-ratio: 1;\r\n\t\tborder-radius: 100px;\r\n\t\tborder: 2px solid #444;\r\n\t\tposition: absolute;\r\n\t\tbackground-color: white;\r\n\t\tbox-shadow: 2px 2px 16px #000a;\r\n\t\ttransform: translateX( -50% );\r\n\t\tpointer-events: none;\r\n\t}\r\n}\r\n"
},
{
"Ident": "facepunch.breakout",
"Path": "ui/components/packagelist.razor.scss",
"FileName": "packagelist.razor.scss",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": ".package-list\r\n{\r\n flex-shrink: 1;\r\n flex-wrap: wrap;\r\n flex-grow: 1;\r\n\r\n h1\r\n {\r\n width: 100%;\r\n margin-top: 50px;\r\n font-size: 40px;\r\n }\r\n\r\n PackageCard\r\n {\r\n &:hover\r\n {\r\n sound-in: \"ui.button.over\";\r\n }\r\n }\r\n\r\n VirtualGrid\r\n {\r\n width: 100%;\r\n height: 100%;\r\n\r\n .cell\r\n {\r\n \r\n }\r\n }\r\n}"
},
{
"Ident": "facepunch.breakout",
"Path": "Level/BlockPalette.cs",
"FileName": "BlockPalette.cs",
"PackageType": "game",
"CodeKind": "Game",
"AssetVersionId": 307874,
"IsPrivate": false,
"Code": "using Sandbox;\r\n\r\nnamespace Breakout;\r\n\r\n/// <summary>\r\n/// Maps level symbols to the colors used when drawing a level's thumbnail preview. This is only for\r\n/// the editor preview image; the in-game bricks get their color from the spawner's palette.\r\n/// </summary>\r\npublic static class BlockPalette\r\n{\r\n\tpublic static readonly Color Background = new( 0.07f, 0.08f, 0.10f );\r\n\tpublic static readonly Color Empty = new( 0.16f, 0.17f, 0.19f );\r\n\r\n\t/// <summary>\r\n\t/// The preview color for a level symbol (falls back to the empty-cell color for unknown symbols).\r\n\t/// </summary>\r\n\tpublic static Color ColorFor( char symbol )\r\n\t{\r\n\t\treturn symbol switch\r\n\t\t{\r\n\t\t\t'1' => new Color( 0.95f, 0.62f, 0.20f ), // normal\r\n\t\t\t'2' => new Color( 0.36f, 0.55f, 0.78f ), // multi-hit\r\n\t\t\t'P' => new Color( 0.35f, 0.78f, 0.42f ), // power-up (multi-ball)\r\n\t\t\t'E' => new Color( 0.30f, 0.78f, 0.80f ), // expand\r\n\t\t\t'X' => new Color( 0.86f, 0.27f, 0.27f ), // exploding\r\n\t\t\t'#' => new Color( 0.55f, 0.55f, 0.58f ), // unbreakable\r\n\t\t\t'S' => new Color( 1.00f, 0.45f, 0.20f ), // fast ball\r\n\t\t\t'B' => new Color( 0.40f, 0.70f, 1.00f ), // big ball\r\n\t\t\t'F' => new Color( 1.00f, 0.35f, 0.10f ), // fireball\r\n\t\t\t_ => Empty,\r\n\t\t};\r\n\t}\r\n}\r\n"
}
]
}