Adds IThrown, ILand interfaces. Adds dice. (#273)

* Dice, IThrown, ILand

* Adds sounds to the dice using a sound collection.

* Seed random instance better.

* Missed a ")", should compile now
This commit is contained in:
Víctor Aguilera Puerto
2019-07-18 23:33:02 +02:00
committed by Pieter-Jan Briers
parent 92668432a7
commit d9077bde74
92 changed files with 447 additions and 5 deletions

View File

@@ -78,6 +78,8 @@ namespace Content.Client
factory.RegisterIgnore("Stack"); factory.RegisterIgnore("Stack");
factory.RegisterIgnore("Dice");
factory.Register<HandsComponent>(); factory.Register<HandsComponent>();
factory.RegisterReference<HandsComponent, IHandsComponent>(); factory.RegisterReference<HandsComponent, IHandsComponent>();
factory.Register<ClientStorageComponent>(); factory.Register<ClientStorageComponent>();

View File

@@ -56,6 +56,7 @@ using Content.Server.GameObjects.Components.Research;
using Content.Shared.GameObjects.Components.Research; using Content.Shared.GameObjects.Components.Research;
using Robust.Shared.Interfaces.Log; using Robust.Shared.Interfaces.Log;
using Content.Server.GameObjects.Components.Explosive; using Content.Server.GameObjects.Components.Explosive;
using Content.Server.GameObjects.Components.Items;
using Content.Server.GameObjects.Components.Triggers; using Content.Server.GameObjects.Components.Triggers;
namespace Content.Server namespace Content.Server
@@ -180,6 +181,8 @@ namespace Content.Server
factory.Register<CatwalkComponent>(); factory.Register<CatwalkComponent>();
factory.Register<DiceComponent>();
factory.Register<ExplosiveComponent>(); factory.Register<ExplosiveComponent>();
factory.Register<OnUseTimerTriggerComponent>(); factory.Register<OnUseTimerTriggerComponent>();

View File

@@ -430,6 +430,18 @@ namespace Content.Server.GameObjects
} }
} }
public bool ThrowItem()
{
var item = GetActiveHand?.Owner;
if (item != null)
{
var interactionSystem = _entitySystemManager.GetEntitySystem<InteractionSystem>();
return interactionSystem.TryThrowInteraction(Owner, item);
}
return false;
}
public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null, public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null,
IComponent component = null) IComponent component = null)
{ {

View File

@@ -0,0 +1,101 @@
using System;
using Content.Server.GameObjects.Components.Sound;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Audio;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Items
{
public class DiceComponent : Component, IActivate, IUse, ILand, IExamine
{
#pragma warning disable 649
[Dependency] private readonly IPrototypeManager _prototypeManager;
#pragma warning restore 649
public override string Name => "Dice";
private Random _random;
private int _step = 1;
private int _sides = 20;
private int _currentSide = 20;
[ViewVariables]
public string _soundCollectionName = "dice";
[ViewVariables]
public int Step => _step;
[ViewVariables]
public int Sides => _sides;
[ViewVariables]
public int CurrentSide => _currentSide;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _step, "step", 1);
serializer.DataField(ref _sides, "sides", 20);
serializer.DataField(ref _soundCollectionName, "diceSoundCollection", "dice");
_currentSide = _sides;
}
public override void OnAdd()
{
base.OnAdd();
_random = new Random(Owner.Uid.GetHashCode() ^ DateTime.Now.GetHashCode());
}
public void Roll()
{
_currentSide = _random.Next(1, (_sides/_step)+1) * _step;
if (!Owner.TryGetComponent(out SpriteComponent sprite)) return;
sprite.LayerSetState(0, $"d{_sides}{_currentSide}");
PlayDiceEffect();
}
public void PlayDiceEffect()
{
if (!string.IsNullOrWhiteSpace(_soundCollectionName))
{
var soundCollection = _prototypeManager.Index<SoundCollectionPrototype>(_soundCollectionName);
var file = _random.Pick(soundCollection.PickFiles);
Owner.GetComponent<SoundComponent>().Play(file, AudioParams.Default);
}
}
public void Activate(ActivateEventArgs eventArgs)
{
Roll();
}
public bool UseEntity(UseEntityEventArgs eventArgs)
{
Roll();
return false;
}
public void Land(LandEventArgs eventArgs)
{
Roll();
}
public void Examine(FormattedMessage message)
{
message.AddText("A dice with ");
message.PushColor(new Color(1F, 0.75F, 0.75F));
message.AddText(_sides.ToString());
message.Pop();
message.AddText(" sides.\nIt has landed on a ");
message.PushColor(new Color(1F, 1F, 1F));
message.AddText(_currentSide.ToString());
message.Pop();
message.AddText(".");
}
}
}

View File

@@ -46,6 +46,11 @@ namespace Content.Server.GameObjects
{ {
return true; return true;
} }
bool IActionBlocker.CanThrow()
{
return true;
}
} }
/// <summary> /// <summary>
@@ -77,6 +82,11 @@ namespace Content.Server.GameObjects
{ {
return false; return false;
} }
bool IActionBlocker.CanThrow()
{
return false;
}
} }
/// <summary> /// <summary>
@@ -118,5 +128,10 @@ namespace Content.Server.GameObjects
{ {
return false; return false;
} }
bool IActionBlocker.CanThrow()
{
return false;
}
} }
} }

View File

@@ -76,6 +76,11 @@ namespace Content.Server.GameObjects
return CurrentDamageState.CanUse(); return CurrentDamageState.CanUse();
} }
bool IActionBlocker.CanThrow()
{
return CurrentDamageState.CanThrow();
}
List<DamageThreshold> IOnDamageBehavior.GetAllDamageThresholds() List<DamageThreshold> IOnDamageBehavior.GetAllDamageThresholds()
{ {
var thresholdlist = DamageTemplate.DamageThresholds; var thresholdlist = DamageTemplate.DamageThresholds;

View File

@@ -1,17 +1,29 @@
using System.Collections.Generic; using System.Collections.Generic;
using Content.Server.GameObjects.Components.Projectiles; using Content.Server.GameObjects.Components.Projectiles;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.GameObjects; using Content.Shared.GameObjects;
using Content.Shared.Physics; using Content.Shared.Physics;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.GameObjects.Components; using Robust.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.IoC;
namespace Content.Server.GameObjects.Components namespace Content.Server.GameObjects.Components
{ {
class ThrownItemComponent : ProjectileComponent, ICollideBehavior class ThrownItemComponent : ProjectileComponent, ICollideBehavior
{ {
#pragma warning disable 649
[Dependency] private readonly IEntitySystemManager _entitySystemManager;
#pragma warning restore 649
public override string Name => "ThrownItem"; public override string Name => "ThrownItem";
/// <summary>
/// User who threw the item.
/// </summary>
public IEntity User;
void ICollideBehavior.CollideWith(List<IEntity> collidedwith) void ICollideBehavior.CollideWith(List<IEntity> collidedwith)
{ {
foreach (var entity in collidedwith) foreach (var entity in collidedwith)
@@ -31,9 +43,13 @@ namespace Content.Server.GameObjects.Components
body.CollisionMask &= (int)~CollisionGroup.Mob; body.CollisionMask &= (int)~CollisionGroup.Mob;
body.IsScrapingFloor = true; body.IsScrapingFloor = true;
// KYS, your job is finished. // KYS, your job is finished. Trigger ILand as well.
Owner.RemoveComponent<ThrownItemComponent>(); Owner.RemoveComponent<ThrownItemComponent>();
} _entitySystemManager.GetEntitySystem<InteractionSystem>().LandInteraction(User, Owner, Owner.Transform.GridPosition);
}
} }
} }
} }

View File

@@ -10,6 +10,8 @@ namespace Content.Server.GameObjects.EntitySystems
bool CanInteract(); bool CanInteract();
bool CanUse(); bool CanUse();
bool CanThrow();
} }
public class ActionBlockerSystem : EntitySystem public class ActionBlockerSystem : EntitySystem
@@ -43,5 +45,15 @@ namespace Content.Server.GameObjects.EntitySystems
} }
return canuse; return canuse;
} }
public static bool CanThrow(IEntity entity)
{
bool canthrow = true;
foreach (var actionblockercomponents in entity.GetAllComponents<IActionBlocker>())
{
canthrow &= actionblockercomponents.CanThrow();
}
return canthrow;
}
} }
} }

View File

@@ -125,6 +125,44 @@ namespace Content.Server.GameObjects.EntitySystems
public IEntity User { get; set; } public IEntity User { get; set; }
} }
/// <summary>
/// This interface gives components behavior when thrown.
/// </summary>
public interface IThrown
{
void Thrown(ThrownEventArgs eventArgs);
}
public class ThrownEventArgs : EventArgs
{
public ThrownEventArgs(IEntity user)
{
User = user;
}
public IEntity User { get; }
}
/// <summary>
/// This interface gives components behavior when landing after being thrown.
/// </summary>
public interface ILand
{
void Land(LandEventArgs eventArgs);
}
public class LandEventArgs : EventArgs
{
public LandEventArgs(IEntity user, GridCoordinates landingLocation)
{
User = user;
LandingLocation = landingLocation;
}
public IEntity User { get; }
public GridCoordinates LandingLocation { get; }
}
public interface IAttack public interface IAttack
{ {
void Attack(AttackEventArgs eventArgs); void Attack(AttackEventArgs eventArgs);
@@ -462,6 +500,63 @@ namespace Content.Server.GameObjects.EntitySystems
} }
} }
/// <summary>
/// Activates the Use behavior of an object
/// Verifies that the user is capable of doing the use interaction first
/// </summary>
public bool TryThrowInteraction(IEntity user, IEntity item)
{
if (user == null || item == null || !ActionBlockerSystem.CanThrow(user)) return false;
ThrownInteraction(user, item);
return true;
}
/// <summary>
/// Calls Thrown on all components that implement the IThrown interface
/// on an entity that has been thrown.
/// </summary>
public void ThrownInteraction(IEntity user, IEntity thrown)
{
var throwMsg = new ThrownMessage(user, thrown);
RaiseEvent(throwMsg);
if (throwMsg.Handled)
{
return;
}
var comps = thrown.GetAllComponents<IThrown>().ToList();
// Call Thrown on all components that implement the interface
foreach (var comp in comps)
{
comp.Thrown(new ThrownEventArgs(user));
}
}
/// <summary>
/// Calls Land on all components that implement the ILand interface
/// on an entity that has landed after being thrown.
/// </summary>
public void LandInteraction(IEntity user, IEntity landing, GridCoordinates landLocation)
{
var landMsg = new LandMessage(user, landing, landLocation);
RaiseEvent(landMsg);
if (landMsg.Handled)
{
return;
}
var comps = landing.GetAllComponents<ILand>().ToList();
// Call Land on all components that implement the interface
foreach (var comp in comps)
{
comp.Land(new LandEventArgs(user, landLocation));
}
}
/// <summary> /// <summary>
/// Will have two behaviors, either "uses" the weapon at range on the entity if it is capable of accepting that action /// Will have two behaviors, either "uses" the weapon at range on the entity if it is capable of accepting that action
/// Or it will use the weapon itself on the position clicked, regardless of what was there /// Or it will use the weapon itself on the position clicked, regardless of what was there
@@ -715,6 +810,68 @@ namespace Content.Server.GameObjects.EntitySystems
} }
} }
/// <summary>
/// Raised when throwing the entity in your hands.
/// </summary>
[PublicAPI]
public class ThrownMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity that threw the item.
/// </summary>
public IEntity User { get; }
/// <summary>
/// Item that was thrown.
/// </summary>
public IEntity Thrown { get; }
public ThrownMessage(IEntity user, IEntity thrown)
{
User = user;
Thrown = thrown;
}
}
/// <summary>
/// Raised when an entity that was thrown lands.
/// </summary>
[PublicAPI]
public class LandMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity that threw the item.
/// </summary>
public IEntity User { get; }
/// <summary>
/// Item that was thrown.
/// </summary>
public IEntity Thrown { get; }
/// <summary>
/// Location where the item landed.
/// </summary>
public GridCoordinates LandLocation { get; }
public LandMessage(IEntity user, IEntity thrown, GridCoordinates landLocation)
{
User = user;
Thrown = thrown;
LandLocation = landLocation;
}
}
/// <summary> /// <summary>
/// Raised when an entity is activated in the world. /// Raised when an entity is activated in the world.
/// </summary> /// </summary>

View File

@@ -135,6 +135,9 @@ namespace Content.Server.GameObjects.EntitySystems
var throwEnt = handsComp.GetHand(handsComp.ActiveIndex).Owner; var throwEnt = handsComp.GetHand(handsComp.ActiveIndex).Owner;
if (!handsComp.ThrowItem())
return;
// pop off an item, or throw the single item in hand. // pop off an item, or throw the single item in hand.
if (!throwEnt.TryGetComponent(out StackComponent stackComp) || stackComp.Count < 2) if (!throwEnt.TryGetComponent(out StackComponent stackComp) || stackComp.Count < 2)
{ {
@@ -147,9 +150,7 @@ namespace Content.Server.GameObjects.EntitySystems
} }
if (!throwEnt.TryGetComponent(out CollidableComponent colComp)) if (!throwEnt.TryGetComponent(out CollidableComponent colComp))
{
return; return;
}
colComp.CollisionEnabled = true; colComp.CollisionEnabled = true;
// I can now collide with player, so that i can do damage. // I can now collide with player, so that i can do damage.
@@ -161,15 +162,14 @@ namespace Content.Server.GameObjects.EntitySystems
colComp.IsScrapingFloor = false; colComp.IsScrapingFloor = false;
} }
projComp.User = plyEnt;
projComp.IgnoreEntity(plyEnt); projComp.IgnoreEntity(plyEnt);
var transform = plyEnt.Transform; var transform = plyEnt.Transform;
var dirVec = (coords.ToWorld(_mapManager).Position - transform.WorldPosition).Normalized; var dirVec = (coords.ToWorld(_mapManager).Position - transform.WorldPosition).Normalized;
if (!throwEnt.TryGetComponent(out PhysicsComponent physComp)) if (!throwEnt.TryGetComponent(out PhysicsComponent physComp))
{
physComp = throwEnt.AddComponent<PhysicsComponent>(); physComp = throwEnt.AddComponent<PhysicsComponent>();
}
// TODO: Move this into PhysicsSystem, we need an ApplyForce function. // TODO: Move this into PhysicsSystem, we need an ApplyForce function.
var a = ThrowForce / (float) Math.Max(0.001, physComp.Mass); // a = f / m var a = ThrowForce / (float) Math.Max(0.001, physComp.Mass); // a = f / m
@@ -185,6 +185,8 @@ namespace Content.Server.GameObjects.EntitySystems
lHomoDir.Normalize(); lHomoDir.Normalize();
transform.LocalRotation = new Angle(lHomoDir.Xy); transform.LocalRotation = new Angle(lHomoDir.Xy);
} }
} }
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,106 @@
- type: entity
name: "BaseDice"
parent: BaseItem
id: BaseDice
components:
- type: Dice
- type: Sound
- type: entity
name: "d100"
parent: BaseDice
id: d100
components:
- type: Dice
sides: 100
step: 10
- type: Sprite
sprite: Objects/items/dice.rsi
state: d100100
- type: Icon
sprite: Objects/items/dice.rsi
state: d100100
- type: entity
name: "d20"
parent: BaseDice
id: d20
components:
- type: Dice
sides: 20
- type: Sprite
sprite: Objects/items/dice.rsi
state: d2020
- type: Icon
sprite: Objects/items/dice.rsi
state: d2020
- type: entity
name: "d12"
parent: BaseDice
id: d12
components:
- type: Dice
sides: 12
- type: Sprite
sprite: Objects/items/dice.rsi
state: d1212
- type: Icon
sprite: Objects/items/dice.rsi
state: d1212
- type: entity
name: "d10"
parent: BaseDice
id: d10
components:
- type: Dice
sides: 10
- type: Sprite
sprite: Objects/items/dice.rsi
state: d1010
- type: Icon
sprite: Objects/items/dice.rsi
state: d1010
- type: entity
name: "d8"
parent: BaseDice
id: d8
components:
- type: Dice
sides: 8
- type: Sprite
sprite: Objects/items/dice.rsi
state: d88
- type: Icon
sprite: Objects/items/dice.rsi
state: d88
- type: entity
name: "d6"
parent: BaseDice
id: d6
components:
- type: Dice
sides: 6
- type: Sprite
sprite: Objects/items/dice.rsi
state: d66
- type: Icon
sprite: Objects/items/dice.rsi
state: d66
- type: entity
name: "d4"
parent: BaseDice
id: d4
components:
- type: Dice
sides: 4
- type: Sprite
sprite: Objects/items/dice.rsi
state: d44
- type: Icon
sprite: Objects/items/dice.rsi
state: d44

View File

@@ -0,0 +1,10 @@
- type: sound_collection
id: dice
files:
- /Audio/items/dice/dice1.ogg
- /Audio/items/dice/dice2.ogg
- /Audio/items/dice/dice3.ogg
- /Audio/items/dice/dice4.ogg
- /Audio/items/dice/dice5.ogg
- /Audio/items/dice/dice6.ogg
- /Audio/items/dice/dice7.ogg

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

View File

@@ -0,0 +1 @@
{"version": 1, "size": {"x": 32, "y": 32}, "states": [{"name": "d10010", "directions": 1, "delays": [[1.0]]}, {"name": "d100100", "directions": 1, "delays": [[1.0]]}, {"name": "d10020", "directions": 1, "delays": [[1.0]]}, {"name": "d10030", "directions": 1, "delays": [[1.0]]}, {"name": "d10040", "directions": 1, "delays": [[1.0]]}, {"name": "d10050", "directions": 1, "delays": [[1.0]]}, {"name": "d10060", "directions": 1, "delays": [[1.0]]}, {"name": "d10070", "directions": 1, "delays": [[1.0]]}, {"name": "d10080", "directions": 1, "delays": [[1.0]]}, {"name": "d10090", "directions": 1, "delays": [[1.0]]}, {"name": "d101", "directions": 1, "delays": [[1.0]]}, {"name": "d1010", "directions": 1, "delays": [[1.0]]}, {"name": "d102", "directions": 1, "delays": [[1.0]]}, {"name": "d103", "directions": 1, "delays": [[1.0]]}, {"name": "d104", "directions": 1, "delays": [[1.0]]}, {"name": "d105", "directions": 1, "delays": [[1.0]]}, {"name": "d106", "directions": 1, "delays": [[1.0]]}, {"name": "d107", "directions": 1, "delays": [[1.0]]}, {"name": "d108", "directions": 1, "delays": [[1.0]]}, {"name": "d109", "directions": 1, "delays": [[1.0]]}, {"name": "d121", "directions": 1, "delays": [[1.0]]}, {"name": "d1210", "directions": 1, "delays": [[1.0]]}, {"name": "d1211", "directions": 1, "delays": [[1.0]]}, {"name": "d1212", "directions": 1, "delays": [[1.0]]}, {"name": "d122", "directions": 1, "delays": [[1.0]]}, {"name": "d123", "directions": 1, "delays": [[1.0]]}, {"name": "d124", "directions": 1, "delays": [[1.0]]}, {"name": "d125", "directions": 1, "delays": [[1.0]]}, {"name": "d126", "directions": 1, "delays": [[1.0]]}, {"name": "d127", "directions": 1, "delays": [[1.0]]}, {"name": "d128", "directions": 1, "delays": [[1.0]]}, {"name": "d129", "directions": 1, "delays": [[1.0]]}, {"name": "d201", "directions": 1, "delays": [[1.0]]}, {"name": "d2010", "directions": 1, "delays": [[1.0]]}, {"name": "d2011", "directions": 1, "delays": [[1.0]]}, {"name": "d2012", "directions": 1, "delays": [[1.0]]}, {"name": "d2013", "directions": 1, "delays": [[1.0]]}, {"name": "d2014", "directions": 1, "delays": [[1.0]]}, {"name": "d2015", "directions": 1, "delays": [[1.0]]}, {"name": "d2016", "directions": 1, "delays": [[1.0]]}, {"name": "d2017", "directions": 1, "delays": [[1.0]]}, {"name": "d2018", "directions": 1, "delays": [[1.0]]}, {"name": "d2019", "directions": 1, "delays": [[1.0]]}, {"name": "d202", "directions": 1, "delays": [[1.0]]}, {"name": "d2020", "directions": 1, "delays": [[1.0]]}, {"name": "d203", "directions": 1, "delays": [[1.0]]}, {"name": "d204", "directions": 1, "delays": [[1.0]]}, {"name": "d205", "directions": 1, "delays": [[1.0]]}, {"name": "d206", "directions": 1, "delays": [[1.0]]}, {"name": "d207", "directions": 1, "delays": [[1.0]]}, {"name": "d208", "directions": 1, "delays": [[1.0]]}, {"name": "d209", "directions": 1, "delays": [[1.0]]}, {"name": "d41", "directions": 1, "delays": [[1.0]]}, {"name": "d42", "directions": 1, "delays": [[1.0]]}, {"name": "d43", "directions": 1, "delays": [[1.0]]}, {"name": "d44", "directions": 1, "delays": [[1.0]]}, {"name": "d61", "directions": 1, "delays": [[1.0]]}, {"name": "d62", "directions": 1, "delays": [[1.0]]}, {"name": "d63", "directions": 1, "delays": [[1.0]]}, {"name": "d64", "directions": 1, "delays": [[1.0]]}, {"name": "d65", "directions": 1, "delays": [[1.0]]}, {"name": "d66", "directions": 1, "delays": [[1.0]]}, {"name": "d81", "directions": 1, "delays": [[1.0]]}, {"name": "d82", "directions": 1, "delays": [[1.0]]}, {"name": "d83", "directions": 1, "delays": [[1.0]]}, {"name": "d84", "directions": 1, "delays": [[1.0]]}, {"name": "d85", "directions": 1, "delays": [[1.0]]}, {"name": "d86", "directions": 1, "delays": [[1.0]]}, {"name": "d87", "directions": 1, "delays": [[1.0]]}, {"name": "d88", "directions": 1, "delays": [[1.0]]}, {"name": "dicebag", "directions": 1, "delays": [[1.0]]}, {"name": "magicdicebag", "directions": 1, "delays": [[1.0]]}]}