From 2904a368f723f9c6d1b7816d1fda48783e49e16c Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Sat, 21 Jan 2023 12:51:26 +1300 Subject: [PATCH] Dice tweaks (#13514) --- Content.Client/Dice/DiceSystem.cs | 21 +++ Content.Server/Dice/DiceComponent.cs | 20 --- Content.Server/Dice/DiceSystem.cs | 89 +++-------- Content.Shared/Dice/DiceComponent.cs | 44 ++++++ Content.Shared/Dice/SharedDiceSystem.cs | 93 ++++++++++++ Resources/Maps/box.yml | 6 +- Resources/Maps/centcomm.yml | 2 +- Resources/Maps/marathon.yml | 2 +- .../Prototypes/Catalog/Cargo/cargo_fun.yml | 2 +- .../Prototypes/Entities/Objects/Fun/dice.yml | 32 ++-- .../Entities/Objects/Fun/dice_bag.yml | 2 +- .../Textures/Objects/Fun/dice.rsi/d10010.png | Bin 361 -> 0 bytes .../Textures/Objects/Fun/dice.rsi/d100100.png | Bin 359 -> 0 bytes .../Textures/Objects/Fun/dice.rsi/d10020.png | Bin 369 -> 0 bytes .../Textures/Objects/Fun/dice.rsi/d10030.png | Bin 372 -> 0 bytes .../Textures/Objects/Fun/dice.rsi/d10040.png | Bin 372 -> 0 bytes .../Textures/Objects/Fun/dice.rsi/d10050.png | Bin 372 -> 0 bytes .../Textures/Objects/Fun/dice.rsi/d10060.png | Bin 370 -> 0 bytes .../Textures/Objects/Fun/dice.rsi/d10070.png | Bin 361 -> 0 bytes .../Textures/Objects/Fun/dice.rsi/d10080.png | Bin 369 -> 0 bytes .../Textures/Objects/Fun/dice.rsi/d10090.png | Bin 372 -> 0 bytes .../Fun/dice.rsi/{d101.png => d10_1.png} | Bin .../Fun/dice.rsi/{d1010.png => d10_10.png} | Bin .../Fun/dice.rsi/{d102.png => d10_2.png} | Bin .../Fun/dice.rsi/{d103.png => d10_3.png} | Bin .../Fun/dice.rsi/{d104.png => d10_4.png} | Bin .../Fun/dice.rsi/{d105.png => d10_5.png} | Bin .../Fun/dice.rsi/{d106.png => d10_6.png} | Bin .../Fun/dice.rsi/{d107.png => d10_7.png} | Bin .../Fun/dice.rsi/{d108.png => d10_8.png} | Bin .../Fun/dice.rsi/{d109.png => d10_9.png} | Bin .../Fun/dice.rsi/{d121.png => d12_1.png} | Bin .../Fun/dice.rsi/{d1210.png => d12_10.png} | Bin .../Fun/dice.rsi/{d1211.png => d12_11.png} | Bin .../Fun/dice.rsi/{d1212.png => d12_12.png} | Bin .../Fun/dice.rsi/{d122.png => d12_2.png} | Bin .../Fun/dice.rsi/{d123.png => d12_3.png} | Bin .../Fun/dice.rsi/{d124.png => d12_4.png} | Bin .../Fun/dice.rsi/{d125.png => d12_5.png} | Bin .../Fun/dice.rsi/{d126.png => d12_6.png} | Bin .../Fun/dice.rsi/{d127.png => d12_7.png} | Bin .../Fun/dice.rsi/{d128.png => d12_8.png} | Bin .../Fun/dice.rsi/{d129.png => d12_9.png} | Bin .../Fun/dice.rsi/{d201.png => d20_1.png} | Bin .../Fun/dice.rsi/{d2010.png => d20_10.png} | Bin .../Fun/dice.rsi/{d2011.png => d20_11.png} | Bin .../Fun/dice.rsi/{d2012.png => d20_12.png} | Bin .../Fun/dice.rsi/{d2013.png => d20_13.png} | Bin .../Fun/dice.rsi/{d2014.png => d20_14.png} | Bin .../Fun/dice.rsi/{d2015.png => d20_15.png} | Bin .../Fun/dice.rsi/{d2016.png => d20_16.png} | Bin .../Fun/dice.rsi/{d2017.png => d20_17.png} | Bin .../Fun/dice.rsi/{d2018.png => d20_18.png} | Bin .../Fun/dice.rsi/{d2019.png => d20_19.png} | Bin .../Fun/dice.rsi/{d202.png => d20_2.png} | Bin .../Fun/dice.rsi/{d2020.png => d20_20.png} | Bin .../Fun/dice.rsi/{d203.png => d20_3.png} | Bin .../Fun/dice.rsi/{d204.png => d20_4.png} | Bin .../Fun/dice.rsi/{d205.png => d20_5.png} | Bin .../Fun/dice.rsi/{d206.png => d20_6.png} | Bin .../Fun/dice.rsi/{d207.png => d20_7.png} | Bin .../Fun/dice.rsi/{d208.png => d20_8.png} | Bin .../Fun/dice.rsi/{d209.png => d20_9.png} | Bin .../Fun/dice.rsi/{d41.png => d4_1.png} | Bin .../Fun/dice.rsi/{d42.png => d4_2.png} | Bin .../Fun/dice.rsi/{d43.png => d4_3.png} | Bin .../Fun/dice.rsi/{d44.png => d4_4.png} | Bin .../Fun/dice.rsi/{d61.png => d6_1.png} | Bin .../Fun/dice.rsi/{d62.png => d6_2.png} | Bin .../Fun/dice.rsi/{d63.png => d6_3.png} | Bin .../Fun/dice.rsi/{d64.png => d6_4.png} | Bin .../Fun/dice.rsi/{d65.png => d6_5.png} | Bin .../Fun/dice.rsi/{d66.png => d6_6.png} | Bin .../Fun/dice.rsi/{d81.png => d8_1.png} | Bin .../Fun/dice.rsi/{d82.png => d8_2.png} | Bin .../Fun/dice.rsi/{d83.png => d8_3.png} | Bin .../Fun/dice.rsi/{d84.png => d8_4.png} | Bin .../Fun/dice.rsi/{d85.png => d8_5.png} | Bin .../Fun/dice.rsi/{d86.png => d8_6.png} | Bin .../Fun/dice.rsi/{d87.png => d8_7.png} | Bin .../Fun/dice.rsi/{d88.png => d8_8.png} | Bin .../Textures/Objects/Fun/dice.rsi/meta.json | 142 +++++++++--------- .../Objects/Fun/dice.rsi/percentile_0.png | Bin 0 -> 2151 bytes .../Objects/Fun/dice.rsi/percentile_10.png | Bin 0 -> 2120 bytes .../Objects/Fun/dice.rsi/percentile_20.png | Bin 0 -> 2176 bytes .../Objects/Fun/dice.rsi/percentile_30.png | Bin 0 -> 2223 bytes .../Objects/Fun/dice.rsi/percentile_40.png | Bin 0 -> 2202 bytes .../Objects/Fun/dice.rsi/percentile_50.png | Bin 0 -> 2171 bytes .../Objects/Fun/dice.rsi/percentile_60.png | Bin 0 -> 2193 bytes .../Objects/Fun/dice.rsi/percentile_70.png | Bin 0 -> 2120 bytes .../Objects/Fun/dice.rsi/percentile_80.png | Bin 0 -> 2146 bytes .../Objects/Fun/dice.rsi/percentile_90.png | Bin 0 -> 2167 bytes 92 files changed, 274 insertions(+), 181 deletions(-) create mode 100644 Content.Client/Dice/DiceSystem.cs delete mode 100644 Content.Server/Dice/DiceComponent.cs create mode 100644 Content.Shared/Dice/DiceComponent.cs create mode 100644 Content.Shared/Dice/SharedDiceSystem.cs delete mode 100644 Resources/Textures/Objects/Fun/dice.rsi/d10010.png delete mode 100644 Resources/Textures/Objects/Fun/dice.rsi/d100100.png delete mode 100644 Resources/Textures/Objects/Fun/dice.rsi/d10020.png delete mode 100644 Resources/Textures/Objects/Fun/dice.rsi/d10030.png delete mode 100644 Resources/Textures/Objects/Fun/dice.rsi/d10040.png delete mode 100644 Resources/Textures/Objects/Fun/dice.rsi/d10050.png delete mode 100644 Resources/Textures/Objects/Fun/dice.rsi/d10060.png delete mode 100644 Resources/Textures/Objects/Fun/dice.rsi/d10070.png delete mode 100644 Resources/Textures/Objects/Fun/dice.rsi/d10080.png delete mode 100644 Resources/Textures/Objects/Fun/dice.rsi/d10090.png rename Resources/Textures/Objects/Fun/dice.rsi/{d101.png => d10_1.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d1010.png => d10_10.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d102.png => d10_2.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d103.png => d10_3.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d104.png => d10_4.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d105.png => d10_5.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d106.png => d10_6.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d107.png => d10_7.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d108.png => d10_8.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d109.png => d10_9.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d121.png => d12_1.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d1210.png => d12_10.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d1211.png => d12_11.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d1212.png => d12_12.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d122.png => d12_2.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d123.png => d12_3.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d124.png => d12_4.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d125.png => d12_5.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d126.png => d12_6.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d127.png => d12_7.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d128.png => d12_8.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d129.png => d12_9.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d201.png => d20_1.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d2010.png => d20_10.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d2011.png => d20_11.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d2012.png => d20_12.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d2013.png => d20_13.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d2014.png => d20_14.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d2015.png => d20_15.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d2016.png => d20_16.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d2017.png => d20_17.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d2018.png => d20_18.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d2019.png => d20_19.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d202.png => d20_2.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d2020.png => d20_20.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d203.png => d20_3.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d204.png => d20_4.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d205.png => d20_5.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d206.png => d20_6.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d207.png => d20_7.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d208.png => d20_8.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d209.png => d20_9.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d41.png => d4_1.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d42.png => d4_2.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d43.png => d4_3.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d44.png => d4_4.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d61.png => d6_1.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d62.png => d6_2.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d63.png => d6_3.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d64.png => d6_4.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d65.png => d6_5.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d66.png => d6_6.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d81.png => d8_1.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d82.png => d8_2.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d83.png => d8_3.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d84.png => d8_4.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d85.png => d8_5.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d86.png => d8_6.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d87.png => d8_7.png} (100%) rename Resources/Textures/Objects/Fun/dice.rsi/{d88.png => d8_8.png} (100%) create mode 100644 Resources/Textures/Objects/Fun/dice.rsi/percentile_0.png create mode 100644 Resources/Textures/Objects/Fun/dice.rsi/percentile_10.png create mode 100644 Resources/Textures/Objects/Fun/dice.rsi/percentile_20.png create mode 100644 Resources/Textures/Objects/Fun/dice.rsi/percentile_30.png create mode 100644 Resources/Textures/Objects/Fun/dice.rsi/percentile_40.png create mode 100644 Resources/Textures/Objects/Fun/dice.rsi/percentile_50.png create mode 100644 Resources/Textures/Objects/Fun/dice.rsi/percentile_60.png create mode 100644 Resources/Textures/Objects/Fun/dice.rsi/percentile_70.png create mode 100644 Resources/Textures/Objects/Fun/dice.rsi/percentile_80.png create mode 100644 Resources/Textures/Objects/Fun/dice.rsi/percentile_90.png diff --git a/Content.Client/Dice/DiceSystem.cs b/Content.Client/Dice/DiceSystem.cs new file mode 100644 index 0000000000..2d36488257 --- /dev/null +++ b/Content.Client/Dice/DiceSystem.cs @@ -0,0 +1,21 @@ +using Content.Shared.Dice; +using Robust.Client.GameObjects; + +namespace Content.Client.Dice; + +public sealed class DiceSystem : SharedDiceSystem +{ + protected override void UpdateVisuals(EntityUid uid, DiceComponent? die = null) + { + if (!Resolve(uid, ref die) || !TryComp(uid, out SpriteComponent? sprite)) + return; + + // TODO maybe just move each diue to its own RSI? + var state = sprite.LayerGetState(0).Name; + if (state == null) + return; + + var prefix = state.Substring(0, state.IndexOf('_')); + sprite.LayerSetState(0, $"{prefix}_{die.CurrentValue}"); + } +} diff --git a/Content.Server/Dice/DiceComponent.cs b/Content.Server/Dice/DiceComponent.cs deleted file mode 100644 index 70edb26297..0000000000 --- a/Content.Server/Dice/DiceComponent.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Robust.Shared.Audio; - -namespace Content.Server.Dice -{ - [RegisterComponent, Access(typeof(DiceSystem))] - public sealed class DiceComponent : Component - { - [DataField("sound")] - public SoundSpecifier Sound { get; } = new SoundCollectionSpecifier("Dice"); - - [DataField("step")] - public int Step { get; } = 1; - - [DataField("sides")] - public int Sides { get; } = 20; - - [ViewVariables] - public int CurrentSide { get; set; } = 20; - } -} diff --git a/Content.Server/Dice/DiceSystem.cs b/Content.Server/Dice/DiceSystem.cs index 88bffcf95f..30f45937cf 100644 --- a/Content.Server/Dice/DiceSystem.cs +++ b/Content.Server/Dice/DiceSystem.cs @@ -1,81 +1,26 @@ -using Content.Server.Popups; -using Content.Shared.Audio; -using Content.Shared.Examine; -using Content.Shared.Interaction.Events; -using Content.Shared.Throwing; +using Content.Shared.Dice; +using Content.Shared.Popups; using JetBrains.Annotations; -using Robust.Server.GameObjects; -using Robust.Shared.Audio; -using Robust.Shared.Player; using Robust.Shared.Random; -namespace Content.Server.Dice +namespace Content.Server.Dice; + +[UsedImplicitly] +public sealed class DiceSystem : SharedDiceSystem { - [UsedImplicitly] - public sealed class DiceSystem : EntitySystem + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + + public override void Roll(EntityUid uid, DiceComponent? die = null) { - [Dependency] private readonly IRobustRandom _random = default!; + if (!Resolve(uid, ref die)) + return; - public override void Initialize() - { - base.Initialize(); + var roll = _random.Next(1, die.Sides); + SetCurrentSide(uid, roll, die); - SubscribeLocalEvent(OnComponentInit); - SubscribeLocalEvent(OnUseInHand); - SubscribeLocalEvent(OnLand); - SubscribeLocalEvent(OnExamined); - } - - private void OnComponentInit(EntityUid uid, DiceComponent component, ComponentInit args) - { - if (component.CurrentSide > component.Sides) - component.CurrentSide = component.Sides; - } - - private void OnUseInHand(EntityUid uid, DiceComponent component, UseInHandEvent args) - { - if (args.Handled) return; - - args.Handled = true; - Roll(uid, component); - } - - private void OnLand(EntityUid uid, DiceComponent component, ref LandEvent args) - { - Roll(uid, component); - } - - private void OnExamined(EntityUid uid, DiceComponent dice, ExaminedEvent args) - { - //No details check, since the sprite updates to show the side. - args.PushMarkup(Loc.GetString("dice-component-on-examine-message-part-1", ("sidesAmount", dice.Sides))); - args.PushMarkup(Loc.GetString("dice-component-on-examine-message-part-2", ("currentSide", dice.CurrentSide))); - } - - public void SetCurrentSide(EntityUid uid, int side, DiceComponent? die = null, SpriteComponent? sprite = null) - { - if (!Resolve(uid, ref die, ref sprite)) - return; - - side = Math.Min(Math.Max(side, 1), die.Sides); - side += side % die.Step; - - die.CurrentSide = side; - - // TODO DICE: Use a visualizer instead. - sprite.LayerSetState(0, $"d{die.Sides}{die.CurrentSide}"); - } - - public void Roll(EntityUid uid, DiceComponent? die = null) - { - if (!Resolve(uid, ref die)) - return; - - var roll = _random.Next(1, die.Sides/die.Step+1) * die.Step; - SetCurrentSide(uid, roll, die); - - die.Owner.PopupMessageEveryone(Loc.GetString("dice-component-on-roll-land", ("die", die.Owner), ("currentSide", die.CurrentSide))); - SoundSystem.Play(die.Sound.GetSound(), Filter.Pvs(die.Owner), die.Owner, AudioHelpers.WithVariation(0.05f)); - } + _popup.PopupEntity(Loc.GetString("dice-component-on-roll-land", ("die", uid), ("currentSide", die.CurrentValue)), uid); + _audio.PlayPvs(die.Sound, uid); } } diff --git a/Content.Shared/Dice/DiceComponent.cs b/Content.Shared/Dice/DiceComponent.cs new file mode 100644 index 0000000000..357a9714dd --- /dev/null +++ b/Content.Shared/Dice/DiceComponent.cs @@ -0,0 +1,44 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Dice; + +[RegisterComponent, NetworkedComponent, Access(typeof(SharedDiceSystem))] +public sealed class DiceComponent : Component +{ + [DataField("sound")] + public SoundSpecifier Sound { get; } = new SoundCollectionSpecifier("Dice"); + + /// + /// Multiplier for the value of a die. Applied after the . + /// + [DataField("multiplier")] + public int Multiplier { get; } = 1; + + /// + /// Quantity that is subtracted from the value of a die. Can be used to make dice that start at "0". Applied + /// before the + /// + [DataField("offset")] + public int Offset { get; } = 0; + + [DataField("sides")] + public int Sides { get; } = 20; + + /// + /// The currently displayed value. + /// + [DataField("currentValue")] + public int CurrentValue { get; set; } = 20; + + [Serializable, NetSerializable] + public sealed class DiceState : ComponentState + { + public int CurrentSide { get; set; } = 20; + public DiceState(int side) + { + CurrentSide = side; + } + } +} diff --git a/Content.Shared/Dice/SharedDiceSystem.cs b/Content.Shared/Dice/SharedDiceSystem.cs new file mode 100644 index 0000000000..611fcfa8cf --- /dev/null +++ b/Content.Shared/Dice/SharedDiceSystem.cs @@ -0,0 +1,93 @@ +using Content.Shared.Examine; +using Content.Shared.Interaction.Events; +using Content.Shared.Throwing; +using Robust.Shared.GameStates; + +namespace Content.Shared.Dice; + +public abstract class SharedDiceSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnUseInHand); + SubscribeLocalEvent(OnLand); + SubscribeLocalEvent(OnExamined); + SubscribeLocalEvent(OnGetState); + SubscribeLocalEvent(OnHandleState); + } + + private void OnHandleState(EntityUid uid, DiceComponent component, ref ComponentHandleState args) + { + if (args.Current is DiceComponent.DiceState state) + component.CurrentValue = state.CurrentSide; + + UpdateVisuals(uid, component); + } + + private void OnGetState(EntityUid uid, DiceComponent component, ref ComponentGetState args) + { + args.State = new DiceComponent.DiceState(component.CurrentValue); + } + + private void OnUseInHand(EntityUid uid, DiceComponent component, UseInHandEvent args) + { + if (args.Handled) return; + + args.Handled = true; + Roll(uid, component); + } + + private void OnLand(EntityUid uid, DiceComponent component, ref LandEvent args) + { + Roll(uid, component); + } + + private void OnExamined(EntityUid uid, DiceComponent dice, ExaminedEvent args) + { + //No details check, since the sprite updates to show the side. + args.PushMarkup(Loc.GetString("dice-component-on-examine-message-part-1", ("sidesAmount", dice.Sides))); + args.PushMarkup(Loc.GetString("dice-component-on-examine-message-part-2", ("currentSide", dice.CurrentValue))); + } + + public void SetCurrentSide(EntityUid uid, int side, DiceComponent? die = null) + { + if (!Resolve(uid, ref die)) + return; + + if (side < 1 || side > die.Sides) + { + Logger.Error($"Attempted to set die {ToPrettyString(uid)} to an invalid side ({side})."); + return; + } + + die.CurrentValue = (side - die.Offset) * die.Multiplier; + Dirty(die); + UpdateVisuals(uid, die); + } + + public void SetCurrentValue(EntityUid uid, int value, DiceComponent? die = null) + { + if (!Resolve(uid, ref die)) + return; + + if (value % die.Multiplier != 0 || value/ die.Multiplier + die.Offset < 1) + { + Logger.Error($"Attempted to set die {ToPrettyString(uid)} to an invalid value ({value})."); + return; + } + + SetCurrentSide(uid, value / die.Multiplier + die.Offset, die); + } + + protected virtual void UpdateVisuals(EntityUid uid, DiceComponent? die = null) + { + // See client system. + } + + public virtual void Roll(EntityUid uid, DiceComponent? die = null) + { + // See the server system, client cannot predict rolling. + } +} diff --git a/Resources/Maps/box.yml b/Resources/Maps/box.yml index b830f3c7c0..6d0b4f5fb2 100644 --- a/Resources/Maps/box.yml +++ b/Resources/Maps/box.yml @@ -5973,7 +5973,7 @@ entities: parent: 8364 type: Transform - uid: 898 - type: d100Dice + type: PercentileDie components: - pos: 57.5,20.5 parent: 8364 @@ -97138,7 +97138,7 @@ entities: parent: 8364 type: Transform - uid: 10853 - type: d100Dice + type: PercentileDie components: - pos: 56.5,3.5000002 parent: 8364 @@ -97304,7 +97304,7 @@ entities: parent: 8364 type: Transform - uid: 10873 - type: d100Dice + type: PercentileDie components: - pos: 55.5,0.5 parent: 8364 diff --git a/Resources/Maps/centcomm.yml b/Resources/Maps/centcomm.yml index 2f2246716e..cfd60d7053 100644 --- a/Resources/Maps/centcomm.yml +++ b/Resources/Maps/centcomm.yml @@ -33065,7 +33065,7 @@ entities: parent: 0 type: Transform - uid: 3765 - type: d100Dice + type: PercentileDie components: - pos: -18.522638,2.6762333 parent: 0 diff --git a/Resources/Maps/marathon.yml b/Resources/Maps/marathon.yml index 6ba908eb8f..49e1f97fdb 100644 --- a/Resources/Maps/marathon.yml +++ b/Resources/Maps/marathon.yml @@ -156547,7 +156547,7 @@ entities: parent: 30 type: Transform - uid: 19473 - type: d100Dice + type: PercentileDie components: - rot: 1.5707963267948966 rad pos: -57.4998,-65.351234 diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_fun.yml b/Resources/Prototypes/Catalog/Cargo/cargo_fun.yml index d695a66c35..041065a3bb 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_fun.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_fun.yml @@ -52,7 +52,7 @@ id: FunBoardGames icon: sprite: Objects/Fun/dice.rsi - state: d66 + state: d6_6 product: CrateFunBoardGames cost: 1500 category: Fun diff --git a/Resources/Prototypes/Entities/Objects/Fun/dice.yml b/Resources/Prototypes/Entities/Objects/Fun/dice.yml index 35a46a9e5d..4d6d9e7667 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/dice.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/dice.yml @@ -7,6 +7,7 @@ - type: ItemCooldown - type: UseDelay - type: Sprite + netsync: false sprite: Objects/Fun/dice.rsi noRot: true # If their sprites rotate, the number becomes even more illegible than usual. - type: Tag @@ -17,15 +18,17 @@ - type: entity parent: BaseDice - id: d100Dice - name: d100 + id: PercentileDie + name: Percentile Die description: A die with ten sides. Works better for d100 rolls than a golf ball. components: - type: Dice - sides: 100 - step: 10 + sides: 10 + multiplier: 10 + offset: 1 # first side is a 0 + currentValue: 1 - type: Sprite - state: d100100 + state: percentile_0 - type: entity parent: BaseDice @@ -35,8 +38,9 @@ components: - type: Dice sides: 20 + currentValue: 20 - type: Sprite - state: d2020 + state: d20_20 - type: entity parent: BaseDice @@ -46,8 +50,9 @@ components: - type: Dice sides: 12 + currentValue: 12 - type: Sprite - state: d1212 + state: d12_12 - type: entity parent: BaseDice @@ -57,8 +62,9 @@ components: - type: Dice sides: 10 + currentValue: 10 - type: Sprite - state: d1010 + state: d10_10 - type: entity parent: BaseDice @@ -68,8 +74,9 @@ components: - type: Dice sides: 8 + currentValue: 8 - type: Sprite - state: d88 + state: d8_8 - type: entity parent: BaseDice @@ -79,8 +86,9 @@ components: - type: Dice sides: 6 + currentValue: 6 - type: Sprite - state: d66 + state: d6_6 - type: entity parent: BaseDice @@ -90,8 +98,9 @@ components: - type: Dice sides: 4 + currentValue: 4 - type: Sprite - state: d44 + state: d4_4 - type: CollisionWake enabled: false - type: Fixtures @@ -122,3 +131,4 @@ damage: types: Piercing: 5 + # I love this diff --git a/Resources/Prototypes/Entities/Objects/Fun/dice_bag.yml b/Resources/Prototypes/Entities/Objects/Fun/dice_bag.yml index b2b61d452a..3b74279841 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/dice_bag.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/dice_bag.yml @@ -12,7 +12,7 @@ - id: d10Dice - id: d12Dice - id: d20Dice - - id: d100Dice + - id: PercentileDie - type: Sprite netsync: false sprite: Objects/Fun/dice.rsi diff --git a/Resources/Textures/Objects/Fun/dice.rsi/d10010.png b/Resources/Textures/Objects/Fun/dice.rsi/d10010.png deleted file mode 100644 index 93b4f9a4a7e932a16ba706aa699c804161c137c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 361 zcmV-v0ha!WP)a50UitwK{7mVFoQs0cmsk!Oo76Z;0UOqTFO$| z-bM(bzhue&wD*0zyB*+gI2;uT{e)H7->51)Xw3kC0l?vw)qY|i^b^)?4#l%{&!{Hq zRm1}?!uh^K;6=g+wIn11#gnU`ny@wy`UzW~=1B7x!0Yq?-m;M9G1jNKwFxT&^2w*Y zjdm^nZkq{X!>H08co8Q14yL`0$Or%|`WKNE&hfF;{vG5dRAI`B4zdBc_C@4g_^N@x zi^zd(_ZSD!;g;39%^~AKRmgq7*YPZw29x#F8nu_Aqd%3Q_oVdb z19H$bkA(?-o$otQ3R`i2Py!iUIVj>l$vN;zgevZEIR1hs1~GuUCqFDc00000NkvXX Hu0mjfmuR0$ diff --git a/Resources/Textures/Objects/Fun/dice.rsi/d100100.png b/Resources/Textures/Objects/Fun/dice.rsi/d100100.png deleted file mode 100644 index 696a140db3fb563843bc9d9543d2a73305e39dea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 359 zcmV-t0hs=YP)_jBYFT&S%}jRtHab-gpmLm`M9$# zTr2;ZWPGBG>|G?X%Ec_^JTU3D|~B z_h<*v?y{(~>wO`OQsjw{cj{bbNjI2`r`Di3R~`MX4B79?^H6KwxCf}Qyjp+aoF#x7 zjnhzxkk|2=s8X0Z2N)%w6qSSH9Qbe!ymP{JZn0SYf;$4CfV;L@*8Bhf002ovPDHLk FV1nsdpeq0X diff --git a/Resources/Textures/Objects/Fun/dice.rsi/d10020.png b/Resources/Textures/Objects/Fun/dice.rsi/d10020.png deleted file mode 100644 index 0a41ead0571fe20d52ea7566d5f5c5bc02f84662..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 369 zcmV-%0gnEOP)npK1H*p?1_p*p-&Qix#Q}O;;r~_Go#A{W_J2|x z!9{v zP(q>ang_$CyWK=Pf+zd16C?V1mIG?6Mpt429=JFx2)Ny@7`c4BYv- z7jNz$IT6A@k=72lZwZA8K0tCdgvC89Eg%C}T0jp4iX8w;VCV+p^Eph7&&1QYdHf02~mIy@I?nHmNPJrSq|W`gjCB%!6+C7g8~2mEyjwK<=_iW P00000NkvXXu0mjfSBZ_t diff --git a/Resources/Textures/Objects/Fun/dice.rsi/d10030.png b/Resources/Textures/Objects/Fun/dice.rsi/d10030.png deleted file mode 100644 index d87303e7109790f3fcfe282bcee2912fa680f6e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 372 zcmV-)0gL{LP)npK1H*p?1_p*p-&Qix#Q}O;;r~_Go#A{W_J2|x z!9{v zP(q>ang_$CyWK=Pf+zd16C?V1mIG?6Mpt429=JFx2)Ny@7`c4BYv- z7jNz$IT6A@k=72lZwZA8K0tCdgvC89Eg%C}T0jp4e1NDBkmWFeCo&j74gq5IU;_k0 z;L^91j4JHT|6zv00CEVRhX!&e5Gt66F13OLXTei6u3$zNU-v$Zp!q~6LS(~`^F1Y& zljHzoL;J3Iz#Rd@$O)5J%NZC*hyrAQFFHuEoPmMNasZblq*^`-M!_f;6aWAV(TNOv SHNx!x0000RU|STkH1nNl&yXa7-BB`QxrP zzV{56!EC)gMO4gul S$rpA20000SLKSt=Y4NH9j%WcPs#yXb*(0v68uCA0NdN5 zvA*>T&|Ejhr5fWj09ha6~e3{50lat8;8e}OMiScesI Sm>(Aa0000D%46ueHA8iiDoO2dK*0;c@HR1#d0KPd0WKBAJ#_Xi~dK_mNvs-PffL7|n(sup?3 z-b7}^K;)+~9L@AM zd6!%fPkqP(FGhLZBJg4@gc}J&bTQ%7qA`_pC+j%HF7rBL11?WZoaT};-u*8KTHPc$XCMGOF+$3<&> z>lvWMnzHUf&JsY2iagOG)Ki|fItp8IfDr+ODGm-f(BT-GNVwz<4i5hUzc|;0!PrW3 Q(EtDd07*qoM6N<$g7)l$Y- zdl?~!e#w&k^`3KoTEJj17;54<5v#MlRabb}o&o>^fZb);_=y3}iCE7H#ItnIs3w|q z#9iCR@tVQ4ePM*!5|V*p=4DV#XdCdHh^-GZBzXwnkv)K?DkOP`^?^sZ=1^9K^{U*+)qWes;X2$HX!%Dh&&5lHQ?Gl zIk4^;}=9IUL@pNNwT z$U&1l6ejp}yk?>my5az#1u|9bpojw>o&)bhsNx2L;V-xY-YS4&9!X)w00000NkvXX Hu0mjf!q=SO diff --git a/Resources/Textures/Objects/Fun/dice.rsi/d10080.png b/Resources/Textures/Objects/Fun/dice.rsi/d10080.png deleted file mode 100644 index a332d93ca20251fbc42da47decf77a2b5be256a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 369 zcmV-%0gnEOP)m~9k1@N6cfV(Q>Rf=`Jv^HU7 zfM)(a-e}Lt_qLTV4oq9wLqEZM|MKJP>h+|mA~{^Q+P{N6gcO;rsVX|y259f)JV@v) z{HlS_Pg(=(GVl7PiE$B?=VBCj6Cs0AWCfa)pj9$0ChM&=eg04rO$EAy0pRm%W{ht= z12kA$ultCz4A7u?l`0eRI$n0F6}I94qXiUQJ2>J%&pps3!WDNo9RGqFONfKJhf@@e P00000NkvXXu0mjf6}_Ve diff --git a/Resources/Textures/Objects/Fun/dice.rsi/d10090.png b/Resources/Textures/Objects/Fun/dice.rsi/d10090.png deleted file mode 100644 index fe093d1b01787f8b988e304c3a1359c22b1b46b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 372 zcmV-)0gL{LP)R@o=i1 z$-Us3c<3V@1u5!wk0?l$5pGLZ2D+K+;F@qYkc7F|R0|Yk2H+=q0KckGlo>YF!r6qA z0h;+N-Wt!!_pX(&4vensQIO*O@O*Lh zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|ck|Ze({O1&V1cVTREN2SK=bCneHxt~wEf5P{d z_VD;2p@~uQ^|kD~e@DA~KA`z-AFu5}=RHon2cq~gHT%q7zx&mDAWm01-QPpIpX>Q) zJNJK@_pl$^di$OgU@XCSoI=`69C0r`3;REFM@hI7m*lm4)p1X(-^VUIs&C*uYH!%Z zez)^06d{(oLwUpKZYOzb=f^bZWkvKk^UDuZV~fw9C+y5tHQU$jdM-e!gnLsTTRAm! z9DtI~V-Q4=GMqWTqZbGvyD^o6@43R0ZsHTM3AD91 zM3`H!7-BFG3$ak4s3|ECaID~`W95l+8eo7#(xPDCh7k#xYVx`9jMC|wBwfw077!r_ z5d}4kJIKmepdZZ@8tTH5gNPJSsnVnuF1bi4MT>h>SJteeMOCXd?Uie;QcKlZYpcDb z#;`DHrD5d+~k2HAXA)^c(b+pkZS*Ff9+w3bXUI_nHmWEYV zTYb}ply=^-%hp|Y+ufiwW6LI1Os!h8{$TB9^_4YxWA4YS(aoAOmQO$ZWDU)#A48Da zi8yCqEM)@Y>I^{8$vKOaa!$^ia~7K$m?W@9;^ZuH#=v0Sl*H)4-6wNDTc$~+mEkxl8n|p7FJCo@9UEECz8n!Ybdti?R>*|U> zBb|MU&WyH_7ltC4EC~CN!zjH-s%s)=V zhMy`ALwlCKx8c-PF%HA#C|I7Y){s~%5`)L-Y$oW5ECm&ig#BVGD%?{O_)5cpnnuPZ z=IkcJLY1w6LpQ7z0HGOf21ppWNZv?+0KqyqB}^1CW$d$c8wB$+c-_DP;C?~JfM-EK zT#M8?Ec2#;(X@|PM(sel%paf@ZKS$YCRULgqEKAu&^qKR8&z&m9~%4=_6E1w8Lp=j72_fOZ}FgL(7bcwGP| ziAGYGp>G8ns%IzB1@q9$!)bT5O+nk5@W?x`w!beTT|6cM3X1b{!WcF)HLmPL0I|C} z^5r|e!f%`*uO-q|kEMX9fp8@S6mY{DFF@7|Hq~~d#Sp(GUgR(w-dw$H*>Qajv#Vn^cpBoZw2zIo*| zl4k$_010qNS#tmYE+YT{E+YYWr9XB6000McNliru=K&BC5FMRJoD={60T4+3d?faN zQXRoWiRH2!CJc{%oMDjVFo8RS)F@%1#OK%msg7VI#qv#eyBQc57#NDQcEEiP12BHy zH4g>`1_lN{m5eIv&i~PUhaB(deB>NLC?^n|4TA({{l{hj zy04MN*S$|;q*^&Z$PwgNPI4lI8QOQv16~BfFmfS8tmPz!05Ks!isfXN1Gp?9)$&m= d3P!=8007MGdb^c18G--+002ovPDHLkV1fgq>)`+Z literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/dice.rsi/percentile_10.png b/Resources/Textures/Objects/Fun/dice.rsi/percentile_10.png new file mode 100644 index 0000000000000000000000000000000000000000..d0607afd38a1b5d54d305801f0636740eab604e5 GIT binary patch literal 2120 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/dice.rsi/percentile_40.png b/Resources/Textures/Objects/Fun/dice.rsi/percentile_40.png new file mode 100644 index 0000000000000000000000000000000000000000..17da219f2c809429880349726a1fe47db2a134bb GIT binary patch literal 2202 zcmV;L2xa$)P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|clH@85{bv=k1V9MEa>PRsvx8aw9ARfxW_5Mn zuDH(9WN`5I66bLjUvEidZa z|2Fe^&EtCY`MC(dSPXfTL*A4q;$D3h@_!;ln{ZE5v-b-6nd%w;33lPx{RG~#_X)eG z_c*;n5n{b3)K3`Q})l&eQBqq0;w8qr5>uB9wq|L zLT6dUCHQCba+qi@G-#}VK_g}lFq*U>^D=x&MRSNP7s!`;)g4IHTWmjQ;^xbAZ|~raIWk& zjbk`-e#a~jlI+Hm55DILFLo1Oh$S${2j&I^HI7Tf;Phczba*Dr<5)txTqDW41pp%K z%{WXVFc51ZPBlfzSyBRy4g4rho~h&k1`=~#DHymRc!K1XeQ&IhbmnHx*Dyj0h+w#g zfSOJUvPxmtkCX-*QYJ2enJWu7?yQw+sa$K7>M=@%qzFqDktSWVQ7esGZPHrnO?&Qy z5XQZB3BC2+Rk5i;v|_blhU&dZTGDPTQjm^Y}Le?b<-znH>>ZgrBBTLnzeMZ=8TmyPd-?~u*gG1@^He= z85qkYfpKvLV9?n)i!GIsojK<$b`M~j!CGP`XC-G043?cTTY7T$!Q3x-3tYa%TmBhy z!KwRSFc+M%q0g0@<;JOS zVtBi^h2yW=@K+PQYI!UiVz3NpG}D3?uCPh9!|#lv>$^xzDh9R?JbOULigT&p&yq}? zEVE#&mIYCXCo$Z9lrXAR&TUQjEaYsRNe$s)6@bO?e7s4$NG}(%)9Z)Rjc;xEJn&oX zVQ9~)dmFN@uu&K`N5%1M^^U?~B{sx3ncWyOQKg^*lAteC5hl%@5m!1AY90kj%&Er1 zLgOufLpDM!0Kzb$86Y9lB4wil0tD;el(A97mQiO{8wtVB5bFjGfan)w48$xL5Vgv! z4J)+MfHct&>u3r@4cIOmDrZjnA|($m@m}mQe9M4`$KX{JAv1#cfsj6?Fcg*moBn_W z-xG|ID~jX7CRl_c=8ebV1@#)bpQ9=kDIXG};%jJ^ers2iUUwGv^^=VUE!qTM28RiG{?I_5@*x6RAoe_$S2 zX&hWbL25vj85^BERB&X%020V>(=|v@CD@5XU7jV+UvnNQfPz-JlT#$B$dM&;jXMS`_eNKt>G2_IB z9y)JZMUly+9{WF-AP)oAMsR+=8&O*}$XlGH+_PGl?SV-6U8@Fk&jDUzJ%?Toej?XaM`lQ65H82x81C@th!j$y{`4$%7W87NHDgs84j#{kFaGBsvkh^ zwS=J7;3(9s5n= zq=>;V&yFA?d)WkQb9?l~w-4-fqIN^{L&=14Yf48oCip`5t!(nEEP^Be>2MLq6{Lgr za7hD6qX3!R+yKHkA5vl2DmjfTZUGKB3fQAbgdX>)I)HzKSJ1GNbojcpa;NO=ABm_D zoo9gZZpl+3%nZN)vC9-TisT>jLHKS0xmr55r8BqWU67^+I?IaZt2bFEDg;KPR zHQbV(Y9d}bCWVkA5c%ck+7bOYJ1C)I*%johlarjj2uX9i#H7iG;hDUyH>z@QlS0rt8{-S8U+UqL>6>l%(}n*C`Wu3h!8AI8_F6XU=)l33V|M1_cxZzdwH($cRIp$_|j_FhMc6 z%yJh)vGz`e|Ns9Jt%vM_=+d{9j4JHT|IvNN%*Til0?6qAIfoF+2}EbZAi-Jxu~~rb zYh>|t@6#BmRt^wy1UZ(IoCslt_FeOU7r`)$TnG_sImsbFOh}MoIoag^E=x$Yd=!j= cQ7|X~0C?|((gRnK`~Uy|07*qoM6N<$f@OgMvH$=8 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/dice.rsi/percentile_50.png b/Resources/Textures/Objects/Fun/dice.rsi/percentile_50.png new file mode 100644 index 0000000000000000000000000000000000000000..83ce6783ba64dcc06a81655c8fa84821ee5e3e5d GIT binary patch literal 2171 zcmV->2!!{EP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|cb|k3|{AU%j1V9MEa>PUD+#THIPl!yH%hh(z zxO;x)oT;=6iX=fqgdQ38|Nm#<4}5Y>F%*_od#w?l(o4^ZPK(#)YEvxd`+V|!3%@^% zhsTYKAwo;n&${pVigA8_K*~KnK8^>O_d4xf=)Uo`AoroDQQ=*9P>bsEt6Dit+??g3wub`i);k!`z9J}!7zJT}W zyvUQwkgDN6)Z0-` z4-)}rq4QY9CHQCba+s5$TYzkVK_f*NoU`F_M53;=an!sCoGom#1B{aZ17jE$3kW<-IQW` zUX6Y!A37nQStidqWwzO;uDoc${a0NQ zR$G1PP8(9%W%I6EcH4ccL2E`&WCEk-R!?y%HJO;0-2$>Pg4}|nFg>hgB z(DXYjc%NXDTu~esHo-$MF>gd>z*5&?4o?^==ia92kZc1YUKX@5D;U@dbsr^%Ll*mz zs0`*t9JbBN;3S|2sbieOU*|IChZng`Q8U;EPBtHxt1@YRQNJ{A(q19;E6Cq0Zrb_;1-3!f~2>KKun--x8scAiduU(3MX)( zj+v;gpdpM~SqorRxn(T3;!IQ9IX^_FsE^EdL!~Tp!#l31!B^BUrlz|1xCh`tUHt*T z4W-aVfn!zzF@h&VU+gH}eW{Jhk*2xkp#^BZA4hU&x+8h~#etG<;o*h)4yfoPdJJ;y z;oZo3L>{?-cXv7_4dflKxSA1+-}RG7626%VVN~;yY>a{v$V`C4y$UV@x1ZuMv`@R^ z=P}O;j4x10{VGr%t5Ex%QwFDJCA`ra4M;iOd2w!($dbhS0Hw`YWmVLpYvF`DX-6=I z4Q~P~;Y)>mvqcSwe0YaQc%f?#G#OrD4Y?*8&I{^B0%1t32817nM6hu{nkUa1$Ww}w zhJddOO!6AToxI{qCp~$!`x<=-HTWa^LN6!yTYAw=n#LKmIvBqZg(J4V;4}PkP4p%N zSOOadT*OAdGaJ(6NV|Al%QS;%hx)`!dgh#FUM-DxT4@&*VY?vMBfgz zztjG=&~Gk;e2)YWWB3zTg(eQgSh1i0000JJOGiWi-~i_U;xj%u(EtDd32;bRa{vG? zBLDy{BLR4&KXw2B00(qQO+^Ri0T2@$Ef*x?v;Y7BF-b&0R9M4fU>F6XU=)l33V|M1 z_cxZzr+CUSDY|Njt+i?w&)w3ueO z0FvVWGxS_>NAWqTJe3_F%VC0IaEZ=Nh7z5f4FCWCCt45L1<|E%D;ZVTo&O{IuIGw7 zMiN2}4dfg`C?^n|4TA({{l{hjy04MN*S$|;q*^&Z$PwgNPI4lI8QOQv16~BfFmfS8 xtmPz!05Ks!isfXN1Gp?9)$&m=3P!=8003C=hz`JSqa*+T002ovPDHLkV1n7(^fLee literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/dice.rsi/percentile_60.png b/Resources/Textures/Objects/Fun/dice.rsi/percentile_60.png new file mode 100644 index 0000000000000000000000000000000000000000..134f18288fb66fe5e8decb70445b4ea3a3d101c7 GIT binary patch literal 2193 zcmV;C2yXX@P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|ck|Ze({O1&V1V9MEal}JrdxJgxx`?Q(%TloDl z9v(L`h6pWPKkL5dE5`Zr0V((RcpVQi?{(U}(0$`$LGqn_w|ic@7ovQPr~7y4_j6jF z%(?$<=5w3Jb?g0i5rDB6>roDQQ=*9P>bsEt6Dit+??g3wub`i)pYi%NcHz-|1Mks$ z!!GJQPOngeSnmn-4WoNJ@z>ZLgq}~7K6ie(0k(R4{ybx6tC{V~IxQ7Q)o>g2Van-Y zBH%1^9;>(n|BSwztK(`gae}c0HV3X5QcoFZTPkTKO_ug)XPP)-$vX?$oM)yp)<|;C zlP(HyCCdUDR-gtxCRig3=f_#n*|(qlW@^}ZCCtnTizPhq!xg?7{FCdkkeN$2rPv-= z;au4@jbk`-{*756B-xEAAAHXho^%tRh$S${2j&I?HI8eE!Rb?5ba*Dr<5)txTqDW4 z7XU=qn{k*#U?A2+oN9`av!nzZ8~9P2JX6U73?$~fQZR5s@C3;%``&m)(wUn%U&9D3 zAcCoqfEqXo$SQ@QA1MtQQYJ2enJWu7?yQw+sa$K7>M=@%qzFqDktSWVQ7esGZPHrn zO?&Qy5XQZB3BC2+Rk5jJX~olu8LA@>8fEaPLq;2Y=!AS`nLO*1*=C=*@}dRzUv)`X zZS|!)ZAfXC&AV>dZTGDPtr=M{wrXO{y6JXD!{VIb-F_lTX$#Eb_5L z@^He=85qkYfpKvLAn5Fz#gu3r@4cIOmDrZjnA|($m@t$-UeoMf^WALhqkQu@JKu8}`7zRs# zraxi9`vjxpisHDi2_C``^G0L_EOi~`@Pwgq?roY5$u=P3WkDOWf`PqI_fc{s^nvd@qVhRRtpJT0nS7{^BDK(d*Wx%YEcsBSUQ*kabj(|~#W z&z|OOA?DK_JB+B_Yr6ZyJCf}|?whO&se~6RZ)6;t`$NhQ$dR%uxqm7-{IQhZ+VDI; zpd5hZ>fakL9&pZWS}$)!0if{!$PT6~0y70FjJsG3f*iQwt`pBPl3=M0;(#M_7ehid zArv@{bSwtzX1hSSF*zNg79i2H6v6uV<&+<0wA%$t5Dt-?2`V2UUh%6pWO9e=!~X$2 z+|OHL(Rq!!#jw@@XVtg=+R3B$(3kNo6}Kst%p;{7z*Yi`Dw0Bum*KbJMt_?o=<*s zb#O8`GXkk;LLoDP`s)q2tQQE}=B)UIs%kB$z*d>6i;t^C*V~{g4q*%J#e6?t-Q2X^ z5p-lPn~mpo1>;o+x`C5afR73ahn~_=oC(Eml1upY`|YMz|PDT`fH!At3G6EhS4pzQ( zu%|ZsX8rIc1$^O*4hVF#;4)%6rbQ6HWm?H$IJ~)f`!f3Qvuk3p#0bP#?ZdFX!kb~p z=j^Jg?GB46^~*%OMg6P|e>LG(+kY1NdkY~6tsedh=T-~YGd$T@00006VoOIv0N?=U z0OB(~Ine+B010qNS#tmYE+YT{E+YYWr9XB6000McNliru=K&BC9S7Bf8zTS!0X9iQ zK~z}7V_+BsqhJ(_0t$g1SNMNQ^s`WEu_J#u0|NuYe+C8yhD+a8GSbBXdR*cERoI>3 zd?faNQXRoWiRH2!CJc{%oMDjVFo8RS)F@%1#OK%msg7VI#qv#eyBQc57#NDQcEEiP z12BHyH4g>`1_lN{^nwAMuwg%?kGtJIW&-S2%(%nbT$kUob?}@1?av;7GL*1jge~Q z03k<^V>!u*5N2rKH4k_Z48zEU5V4k%90J6I1Syu2T@K)~gjCB%!6+C7g8~2mprnbl Th>&ON00000NkvXXu0mjfnu7vD literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/dice.rsi/percentile_70.png b/Resources/Textures/Objects/Fun/dice.rsi/percentile_70.png new file mode 100644 index 0000000000000000000000000000000000000000..7a437bbc8ebb35b328a2e28a600651ec4a0b754d GIT binary patch literal 2120 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 Y03qXjyB}iE*8l(j07*qoM6N<$g4rMWV*mgE literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/dice.rsi/percentile_90.png b/Resources/Textures/Objects/Fun/dice.rsi/percentile_90.png new file mode 100644 index 0000000000000000000000000000000000000000..bbf2ae0b96aa9686585d37bc7c24000d2cab253a GIT binary patch literal 2167 zcmV--2#EKIP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|ck|Ze({O1&V1V9MEal}JrbAvtpxQNKC%IwE< z_3V7C*<@4&BuM~rcReEP|Ndd&KltRDYA7tN_F5x8rI(%+offap)uvd^{e1HM6TZKU zhvyF&Lxh&DuXW$^732KzfRuZDyp9K%_d4xfD8-kp$#?etJ+IvhQNG60{XO*iIW3>e zx&QOLmwlM^_Pq$eSd8^3hrB6K#J&11 z$LSS{5bHgmzF~BaCw?2J=QjD}MCoJammhM9J%0Xt!p>|pvwc~or2?rMZlfNioE|0) zKuPDZic9d%=*zh}t_Bk)7+YX-;F=-zl!3OTl2+1WX`gnci6fT0v!Km+W;$byB=b3GR_bLplO+Y>9C zE9Zl|qey9gm}3|l65Zt zh_E-~Fi>$xu_oeFQtEhQW*M?(x4$_;u4s-vT)z3Vi-)hjBkriXBCf2N*K3Th2ePu1ZG52%U(#@JPR?a;6U=70}k0p|a z6L!wPSS|^Si!%U0XXh-oR7!T{oU_2g{2ZtVz~V%VN|W0+nVrMth03{HH3#%02agZ@k{DOdbyCDUO${}d}+h` zz%R9jp*^eaZOFR9Mq$_-700vHI|_@H*bw7nc4N#$m4XgPg1s}*$A}&2*ZeGfP_$sl#LPy5Uhh!#zqlaMx9-4Bm_T0tQ$B0qF<0P5VIg4 zYL#0XR%oYz)kH_EqbU$IV7qXroH^}_lsvq|`=rb8B>@kQ!K*4lW(4yCA$?3?7%Tyr z{(uGV6O588isQm2cnC+#8<82X)ODB}dqmX9y-m|0*#<KMoPVtz(LG8ign&G2ba?ZP-VG6#~)oXowSvqE)?iN+SQE}jO= z_SgZ(^j_25C*F~44|3mRT}UOoSa~Dk;M@->Lm)@WuH^oq=GhiAz1w zKj%OS?!=7%mfwx2EimaV&Qk7Kt<3hK*YFF1hOfgWSc;fjU^q`5E(r)y;Ou3)rb9OP z@xxoo9!qRz>)dv;)^NZxx=(pH=LrTCKwg!Za93OtAX>k5ko<<7Fn;QL+YS zdIzCt9xq@aQc*^|x(3u0E_t;#d40VN&jBERBw(%XBRtRqpCnrgw837a{Yof$5ofpi z!9#rO01|rKP}~G07ioez+%e%Hn0#X3iHE~$;`eyvCB_}Fkd7pYGrZ|dH$YvvY=NWS zaRgrYLq5Y7iT|Mx0*(Ur0v?`v39nWj<0FCu;JNxSO`)&5m1p$;iOD0afvtD}Dx`sWuyzFr-|`xD#b5CddHJCgta00v@9 zM??U_0K)*o#&VKp00009a7bBm001r{001r{0eGc9b^rhX2XskIMF-~r5EBs$?&FQ8 z0003NNklnpK1H*p?1_p*p-&Qix#Q}O; z;r~_Go#A{W_J2|x!9Sj5 zA?FZ6If3YG7$i9BKQ;@{eT^)>?tK~~)ye@vjv&W!k`p1!(7tOP@FEz7kqaSWEhjky thzSW&EGN4hz-0-kmXCr_FbW0*002L^002ovPDHLkV1kc+_(T8z literal 0 HcmV?d00001