From 8064eebc0c222286f3b089973fee416d6f09131a Mon Sep 17 00:00:00 2001 From: grach Date: Sat, 4 May 2024 15:03:28 +0300 Subject: [PATCH 1/6] swap branches --- Content.Client/E20/E20System.cs | 22 ++ Content.Server/E20/E20System.Events.cs | 354 ++++++++++++++++++ Content.Server/E20/E20System.cs | 123 ++++++ Content.Shared/E20/E20Component.cs | 72 ++++ Content.Shared/E20/SharedE20System.cs | 78 ++++ Resources/Locale/en-US/e20/events.ftl | 28 ++ Resources/Locale/ru-RU/e20/events.ftl | 40 ++ .../Prototypes/Entities/Objects/Fun/dice.yml | 58 +++ Resources/Prototypes/Polymorphs/admin.yml | 5 + .../Fun/dice.rsi/dice_of_fate_used.png | Bin 0 -> 294 bytes .../Textures/Objects/Fun/dice.rsi/meta.json | 3 + 11 files changed, 783 insertions(+) create mode 100644 Content.Client/E20/E20System.cs create mode 100644 Content.Server/E20/E20System.Events.cs create mode 100644 Content.Server/E20/E20System.cs create mode 100644 Content.Shared/E20/E20Component.cs create mode 100644 Content.Shared/E20/SharedE20System.cs create mode 100644 Resources/Locale/en-US/e20/events.ftl create mode 100644 Resources/Locale/ru-RU/e20/events.ftl create mode 100644 Resources/Textures/Objects/Fun/dice.rsi/dice_of_fate_used.png diff --git a/Content.Client/E20/E20System.cs b/Content.Client/E20/E20System.cs new file mode 100644 index 00000000000..860d2495961 --- /dev/null +++ b/Content.Client/E20/E20System.cs @@ -0,0 +1,22 @@ +using Content.Shared.E20; +using Robust.Client.GameObjects; + +namespace Content.Client.E20; + +public sealed class E20System : SharedE20System +{ + protected override void UpdateVisuals(EntityUid uid, E20Component? 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/E20/E20System.Events.cs b/Content.Server/E20/E20System.Events.cs new file mode 100644 index 00000000000..3f933381ee8 --- /dev/null +++ b/Content.Server/E20/E20System.Events.cs @@ -0,0 +1,354 @@ +using System.Linq; +using System.Numerics; +using Content.Server.Administration.Commands; +using Content.Server.Administration.Systems; +using Content.Server.Body.Systems; +using Content.Server.Changeling; +using Content.Server.Chat.Managers; +using Content.Server.Explosion.EntitySystems; +using Content.Server.Fluids.EntitySystems; +using Content.Server.Ghost.Roles; +using Content.Server.Ghost.Roles.Components; +using Content.Server.Mind; +using Content.Server.Polymorph.Systems; +using Content.Server.Revenant.Components; +using Content.Shared.Access; +using Content.Shared.Access.Components; +using Content.Shared.Access.Systems; +using Content.Shared.Chemistry.Components; +using Content.Shared.Damage; +using Content.Shared.Damage.Components; +using Content.Shared.Damage.Prototypes; +using Content.Shared.Damage.Systems; +using Content.Shared.Dataset; +using Content.Shared.E20; +using Content.Shared.IdentityManagement; +using Content.Shared.Inventory; +using Content.Shared.Mind; +using Content.Shared.Mind.Components; +using Content.Shared.Movement.Components; +using Content.Shared.Movement.Systems; +using Content.Shared.Popups; +using Content.Shared.Throwing; +using Robust.Server.GameObjects; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Configuration; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Server.E20; + +public sealed class E20SystemEvents : EntitySystem +{ + [Dependency] private readonly ExplosionSystem _explosion = default!; + [Dependency] private readonly BodySystem _bodySystem = default!; + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly InventorySystem _inventory = default!; + [Dependency] private readonly PolymorphSystem _polymorphSystem = default!; + [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!; + [Dependency] private readonly StaminaSystem _stamina = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly RejuvenateSystem _rejuvenate = default!; + [Dependency] private readonly GhostRoleSystem _ghost = default!; + [Dependency] private readonly MetaDataSystem _metaData = default!; + [Dependency] private readonly IChatManager _chat = default!; + [Dependency] private readonly SharedAccessSystem _accessSystem = default!; + [Dependency] private readonly SmokeSystem _smoke = default!; + [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly ChangelingRuleSystem _changelingRule = default!; + [Dependency] private readonly SharedMindSystem _minds = default!; + [Dependency] private readonly IEntityManager _entManager = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly ThrowingSystem _throwingSystem = default!; + [Dependency] private readonly TransformSystem _transform = default!; + + public override void Initialize() + { + IoCManager.Register(); + base.Initialize(); + SubscribeLocalEvent(OnTake); + } + + public void ExplosionEvent(EntityUid uid, E20Component comp) + { + float intensity = comp.CurrentValue * 480; // Calculating power of explosion + var coords = _transform.GetMapCoordinates(uid); + + switch (comp.CurrentValue) + { + case 1: + coords = _transform.GetMapCoordinates(comp.LastUser); // Explode user instead of dice + intensity = 100; + _bodySystem.GibBody(comp.LastUser, true); // gibOrgans=true dont gibs the organs + break; + case 20: + intensity *= 10; + break; + } + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-explosion-event"), + Transform(uid).Coordinates, PopupType.Medium); + _explosion.QueueExplosion(coords, "DemolitionCharge", + intensity, 5, 240); + } + + public void FullDestructionEvent(EntityUid uid, E20Component comp) + { + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-full-destruction-event", + ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _bodySystem.GibBody(comp.LastUser); + } + + public void DieEvent(EntityUid uid, E20Component comp) + { + var damage = new DamageSpecifier(_prototypeManager.Index("Slash"), 200); + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-die-event", + ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _damageableSystem.TryChangeDamage(comp.LastUser, damage, true); + } + + public void AngryMobsSpawnEvent(EntityUid uid, E20Component comp) + { + var coords = _transform.GetMapCoordinates(uid); + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-angry-mobs-spawn-event", + ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + EntityManager.SpawnEntities(coords, "MobCarpDungeon", 5); + } + + public void ItemsDestructionEvent(EntityUid uid, E20Component comp) + { + var bodyId = comp.LastUser; + + if (!TryComp(comp.LastUser, out var inventory)) + return; + foreach (var item in _inventory.GetHandOrInventoryEntities(bodyId)) + { + QueueDel(item); + } + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-items-destruction-event", + ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + } + + public void MonkeyPolymorphEvent(EntityUid uid, E20Component comp) + { + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-monkey-polymorph-event", + ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _polymorphSystem.PolymorphEntity(comp.LastUser, "AdminMonkeySmite"); + } + + public void SpeedReduceEvent(EntityUid uid, E20Component comp) + { + if (!TryComp(comp.LastUser, out var movementSpeed)) + return; + + var newSprint = movementSpeed.BaseSprintSpeed / 2; + var newWalk = movementSpeed.BaseWalkSpeed / 2; + + _movementSpeedModifier.ChangeBaseSpeed( + comp.LastUser, + baseWalkSpeed:newWalk, + baseSprintSpeed:newSprint, + acceleration:movementSpeed.Acceleration); + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-speed-reduce-event", + ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + } + + public void ThrowingEvent(EntityUid uid, E20Component comp) + { + var diceCoords = _transform.GetMapCoordinates(uid); + var playerCoords = _transform.GetMapCoordinates(comp.LastUser); + + var direction = diceCoords.Position - playerCoords.Position; + var randomizedDirection = direction + new Vector2(_random.Next(-10, 10), _random.Next(-10, 10)); + + _throwingSystem.TryThrow(comp.LastUser, randomizedDirection, 60, uid); + + var damage = new DamageSpecifier(_prototypeManager.Index("Blunt"), 50); + + _damageableSystem.TryChangeDamage(comp.LastUser, damage, true); + + if (!TryComp(comp.LastUser, out var staminaComponent)) + return; + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-throwing-event", + ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _stamina.TakeStaminaDamage(comp.LastUser, staminaComponent.CritThreshold); + } + + public void DiseaseEvent(EntityUid uid, E20Component comp) + { + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-disease-event", + ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + var blight = EnsureComp(comp.LastUser); + blight.Duration = 0f; + } + + public void NothingEvent(EntityUid uid, E20Component comp) + { + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-nothing-event", + ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + } + + public void CookieEvent(EntityUid uid, E20Component comp) + { + var coords = _transform.GetMapCoordinates(uid); + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-cookie-event"), + Transform(uid).Coordinates, PopupType.Medium); + EntityManager.SpawnEntities(coords, "FoodBakedCookie", 2); + } + + public void RejuvenateEvent(EntityUid uid, E20Component comp) + { + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-rejuvenate-event", + ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _rejuvenate.PerformRejuvenate(comp.LastUser); + } + + public void MoneyEvent(EntityUid uid, E20Component comp) + { + var coords = _transform.GetMapCoordinates(uid); + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-money-event"), + Transform(uid).Coordinates, PopupType.Medium); + EntityManager.SpawnEntities(coords, "SpaceCash1000", 5); + } + + public void RevolverEvent(EntityUid uid, E20Component comp) + { + var coords = _transform.GetMapCoordinates(uid); + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-revolver-event"), + Transform(uid).Coordinates, PopupType.Medium); + EntityManager.SpawnEntities(coords, "WeaponRevolverInspector", 1); + } + + public void MagicWandEvent(EntityUid uid, E20Component comp) + { + List wands = new List() + { + "WeaponWandPolymorphDoor", + "WeaponWandDeath", + "WeaponWandFireball", + "WeaponWandPolymorphCarp", + "WeaponWandPolymorphMonkey", + "WeaponWandPolymorphBread", + "WeaponWandCluwne", + "FoodFrozenPopsicleTrash" // lol + }; + + var roll = _random.Pick(wands); + var coords = _transform.GetMapCoordinates(uid); + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-magic-wand-event", + ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + EntityManager.SpawnEntities(coords, roll, 1); + } + + + public void SlaveEvent(EntityUid uid, E20Component comp) + { + var ghost = EnsureComp(uid); + + ghost.RoleName = Loc.GetString("dice-of-fate-slave-role-name"); + ghost.RoleDescription = Loc.GetString("dice-of-fate-slave-role-description"); + + comp.IsUsed = false; // We dont want to polymorph Dice before the player takes the role + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-slave-event", + ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + } + + private void OnTake(EntityUid uid, GhostRoleComponent comp, TakeGhostRoleEvent args) + { + if (!HasComp(uid)) + { + return; + } + + var e20 = EnsureComp(uid); + var name = _random.Pick(_prototypeManager.Index("names_death_commando").Values); + var ghost = EnsureComp(uid); + var coords = _transform.GetMapCoordinates(uid); + var mob = Spawn("MobHuman", coords); + var meta = MetaData(mob); + + _metaData.SetEntityName(mob, name, meta); + SetOutfitCommand.SetOutfit(mob, "LibrarianGear", EntityManager); + var newMind = _minds.CreateMind(args.Player.UserId, name); + _minds.SetUserId(newMind, args.Player.UserId); + _minds.TransferTo(newMind, mob); + _chat.DispatchServerMessage(args.Player,Loc.GetString("dice-of-fate-slave-server-message", + ("user", Identity.Entity(e20.LastUser, _entManager)))); + + _ghost.UnregisterGhostRole((uid, ghost)); + _polymorphSystem.PolymorphEntity(uid, "DiceShard"); + } + + public void RandomSyndieBundleEvent(EntityUid uid, E20Component comp) + { + List bundles = new List() + { + "ClothingBackpackDuffelSyndicateFilledSMG", + "ClothingBackpackDuffelSyndicateFilledShotgun", + "CrateSyndicateSurplusBundle", + "BriefcaseSyndieSniperBundleFilled", + "ClothingBackpackDuffelSyndicateFilledGrenadeLauncher", + "ClothingBackpackDuffelSyndicateFilledLMG", + "CrateSyndicateSuperSurplusBundle" + }; + + Solution sol = new(); + var smoke = EnsureComp(uid); + var roll = _random.Pick(bundles); + var coords = _transform.GetMapCoordinates(uid); + + Spawn("Smoke", coords); + _smoke.StartSmoke(uid, sol, 2f, 5, smoke); + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-random-syndie-bundle-event"), + Transform(uid).Coordinates, PopupType.Medium); + EntityManager.SpawnEntities(coords, roll, 1); + } + + public void FullAccessEvent(EntityUid uid, E20Component comp) + { + EnsureComp(comp.LastUser); + var allAccess = _prototypeManager + .EnumeratePrototypes() + .Select(p => new ProtoId(p.ID)).ToArray(); + + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-full-access-event", + ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _accessSystem.TrySetTags(comp.LastUser, allAccess); + } + + public void DamageResistEvent(EntityUid uid, E20Component comp) + { + var damageSet = "DiceOfFate"; + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-damage-resist-event", + ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _damageable.SetDamageModifierSetId(comp.LastUser, damageSet); + } + + public void ChangelingTransformationEvent(EntityUid uid, E20Component comp) + { + if (!TryComp(comp.LastUser, out var targetMindComp)) + return; + + if (!_minds.TryGetSession(targetMindComp.Mind, out var session)) + return; + + _popup.PopupCoordinates(Loc.GetString("dice-of-fate-changeling-transformation-event"), + Transform(uid).Coordinates, PopupType.Medium); + _changelingRule.MakeChangeling(comp.LastUser, new ChangelingRuleComponent(), false); + } +} diff --git a/Content.Server/E20/E20System.cs b/Content.Server/E20/E20System.cs new file mode 100644 index 00000000000..58c3ebc4280 --- /dev/null +++ b/Content.Server/E20/E20System.cs @@ -0,0 +1,123 @@ +using System.Reflection; +using Content.Server.Body.Systems; +using Content.Server.Chat.Systems; +using Content.Server.Explosion.EntitySystems; +using Content.Server.Polymorph.Systems; +using Content.Shared.CCVar; +using Content.Shared.E20; +using Content.Shared.Explosion.Components; +using Content.Shared.Popups; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Random; + +namespace Content.Server.E20; + + +public sealed class E20System : SharedE20System +{ + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly ChatSystem _chat = default!; + [Dependency] private readonly TriggerSystem _triggerSystem = default!; + [Dependency] private readonly E20SystemEvents _events = default!; + [Dependency] private readonly PolymorphSystem _polymorphSystem = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnTimerRemove); + } + + private delegate void EventsDelegate(EntityUid uid, E20Component comp); + + private void E20Picker(EntityUid uid, E20Component comp) + { + _events.ExplosionEvent(uid, comp); + _polymorphSystem.PolymorphEntity(uid, "DiceShard"); + } + + private void DiceOfFatePicker(EntityUid uid, E20Component comp) + { + comp.IsUsed = true; + //FIXME + Dictionary events = new Dictionary(); + events[1] = _events.FullDestructionEvent; + events[2] = _events.DieEvent; + events[3] = _events.AngryMobsSpawnEvent; + events[4] = _events.ItemsDestructionEvent; + events[5] = _events.MonkeyPolymorphEvent; + events[6] = _events.SpeedReduceEvent; + events[7] = _events.ThrowingEvent; + events[8] = _events.ExplosionEvent; + events[9] = _events.DiseaseEvent; + events[10] = _events.NothingEvent; + events[11] = _events.CookieEvent; + events[12] = _events.RejuvenateEvent; + events[13] = _events.MoneyEvent; + events[14] = _events.RevolverEvent; + events[15] = _events.MagicWandEvent; + events[16] = _events.SlaveEvent; + events[17] = _events.RandomSyndieBundleEvent; + events[18] = _events.FullAccessEvent; + events[19] = _events.DamageResistEvent; + events[20] = _events.ChangelingTransformationEvent; + + + EventsDelegate method = events[20]; + method(uid, comp); + + if (comp.IsUsed) + { + _polymorphSystem.PolymorphEntity(uid, "DiceShard"); + } + + } + + private void OnTimerRemove(EntityUid uid, ActiveTimerTriggerComponent comp, ComponentRemove args) + { + if (!HasComp(uid)) + { + return; + } + + E20Component e20 = EntityManager.GetComponent(uid); + + + if (e20.DiceType == "E20") + { + E20Picker(uid, e20); + return; + } + + DiceOfFatePicker(uid, e20); + } + + protected override void TimerEvent(EntityUid uid, E20Component? die = null) + { + if (!Resolve(uid, ref die)) + return; + + _triggerSystem.HandleTimerTrigger(uid, uid, die.Delay, 1, 0, die.Beep); + + if (!((die.DiceType == "E20") & ((die.CurrentValue == 1) | (die.CurrentValue == 20)))) + return; + + _audio.PlayPvs(die.SoundDie, uid); + _chat.TrySendInGameICMessage(uid, Loc.GetString("DIE"), InGameICChatType.Speak, true); + } + + protected override void Roll(EntityUid uid, E20Component? die = null) + { + if (!Resolve(uid, ref die)) + return; + + var roll = _random.Next(1, die.Sides + 1); + SetCurrentSide(uid, roll, die); + + _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/E20/E20Component.cs b/Content.Shared/E20/E20Component.cs new file mode 100644 index 00000000000..85d36f8b4f9 --- /dev/null +++ b/Content.Shared/E20/E20Component.cs @@ -0,0 +1,72 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Shared.E20; +[RegisterComponent, NetworkedComponent] +[AutoGenerateComponentState(true)] +public sealed partial class E20Component : Component +{ + + /// + /// Checks activation of dice to prevent double-triple-.. activation in case of double-triple-.. using dice in hands + /// Or rolling value of dice again after activation. + /// + + public bool IsActivated = false; + + public bool IsUsed = false; + + /// + /// Person who used E20. Required when 1 is rolled. + /// + + public EntityUid LastUser; + + //[DataField] + //[AutoNetworkedField] + //public List Events = new(); + + [DataField] + public string DiceType { get; set; } + + /// + /// Delay for dice action(Gib or Explosion). + /// + [DataField] + public float Delay = 3; + + [DataField] + public SoundSpecifier Sound { get; private set; } = new SoundCollectionSpecifier("Dice"); + + [DataField] + + public SoundSpecifier SoundDie { get; private set; } = new SoundPathSpecifier("/Audio/Items/E20/e20_1.ogg"); + + [DataField] + public SoundSpecifier Beep = new SoundPathSpecifier("/Audio/Machines/Nuke/general_beep.ogg"); + + /// + /// Multiplier for the value of a die. Applied after the . + /// + [DataField] + public int Multiplier { get; private set; } = 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] + public int Offset { get; private set; } = 0; + + [DataField] + public int Sides { get; private set; } = 20; + + /// + /// The currently displayed value. + /// + [DataField] + [AutoNetworkedField] + public int CurrentValue { get; set; } = 20; + + +} diff --git a/Content.Shared/E20/SharedE20System.cs b/Content.Shared/E20/SharedE20System.cs new file mode 100644 index 00000000000..952eb91677c --- /dev/null +++ b/Content.Shared/E20/SharedE20System.cs @@ -0,0 +1,78 @@ +using Content.Shared.Interaction.Events; +using Content.Shared.Throwing; + +namespace Content.Shared.E20; + +public abstract class SharedE20System : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnUseInHand); + SubscribeLocalEvent(OnLand); + SubscribeLocalEvent(OnDiceAfterHandleState); + } + + private void OnDiceAfterHandleState(EntityUid uid, E20Component component, ref AfterAutoHandleStateEvent args) + { + UpdateVisuals(uid, component); + } + + private void OnUseInHand(EntityUid uid, E20Component component , UseInHandEvent args) + { + if (component.IsActivated) + { + return; + } + + Roll(uid, component); + component.IsActivated = true; + component.LastUser = args.User; + TimerEvent(uid, component); + + + } + + private void OnLand(EntityUid uid, E20Component component, ref LandEvent args) + { + if (component.IsActivated) + { + return; + } + + Roll(uid, component); + } + + protected void SetCurrentSide(EntityUid uid, int side, E20Component? die = null) + { + if (!Resolve(uid, ref die)) + return; + + if (side < 1 || side > die.Sides) + { + Log.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); + } + + protected virtual void UpdateVisuals(EntityUid uid, E20Component? die = null) + { + // See client system. + } + + protected virtual void TimerEvent(EntityUid uid, E20Component? die = null) + { + // See the server system, client cannot count ¯\_(ツ)_/¯. + } + + protected virtual void Roll(EntityUid uid, E20Component? die = null) + { + // See the server system, client cannot predict rolling. + } + + +} diff --git a/Resources/Locale/en-US/e20/events.ftl b/Resources/Locale/en-US/e20/events.ftl new file mode 100644 index 00000000000..068db242b46 --- /dev/null +++ b/Resources/Locale/en-US/e20/events.ftl @@ -0,0 +1,28 @@ +## Events + +dice-of-fate-full-destruction-event = { $user } turns into ashe! +dice-of-fate-die-event = { $user } dies of a heart attack! +dice-of-fate-angry-mobs-spawn-event = A horde of evil creatures surrounded { $user }! +dice-of-fate-items-destruction-event = An unknown force stole all the items from { $user }! +dice-of-fate-monkey-polymorph-event = { $user } turns into a monkey! +dice-of-fate-speed-reduce-event = Now even the turtle will overtake { $user }... +dice-of-fate-throwing-event = Something throws { $user }! +dice-of-fate-explosion-event = There is an explosion! +dice-of-fate-disease-event = { $user } is infected with an unknown virus! +dice-of-fate-nothing-event = { $user } didn't lose, he didn't want to win! +dice-of-fate-cookie-event = Cookies appear right out of thin air! +dice-of-fate-rejuvenate-event = Even doctors are jealous of the health of { $user }! +dice-of-fate-money-event = What can't money buy? +dice-of-fate-revolver-event = Shall we play roulette? +dice-of-fate-magic-wand-event = Magic lights the way { $user }! +dice-of-fate-slave-event = A faithful servant is coming to { $user } soon! +dice-of-fate-random-syndie-bundle-event = Mysterious box appears out of nowhere! +dice-of-fate-full-access-event = No door can resist {$user}! +dice-of-fate-damage-resist-event = { $user } feels no pain! +dice-of-fate-changeling-transformation-event = Something incredible is happening! + +## Slave event role + +dice-of-fate-slave-role-name = Bookworm +dice-of-fate-slave-role-description = A servant who magically appeared in this world. +dice-of-fate-slave-server-message = You were called from another dimension for the sole purpose of serving {$user}. Follow any of his orders, guard and protect him, now he is your master. diff --git a/Resources/Locale/ru-RU/e20/events.ftl b/Resources/Locale/ru-RU/e20/events.ftl new file mode 100644 index 00000000000..8dc3e62b3a0 --- /dev/null +++ b/Resources/Locale/ru-RU/e20/events.ftl @@ -0,0 +1,40 @@ +## Events + +dice-of-fate-full-destruction-event = { $user } превращается в пепел! +dice-of-fate-die-event = { $user } умирает от сердечного приступа! +dice-of-fate-angry-mobs-spawn-event = Орда злобных существ окружила { $user }! +dice-of-fate-items-destruction-event = Неведомая сила украла все предметы у { $user }! +dice-of-fate-monkey-polymorph-event = { $user } превращается в обезьяну! +dice-of-fate-speed-reduce-event = Теперь даже черепаха обгонит { $user }... +dice-of-fate-throwing-event = Нечто бросает { $user }! +dice-of-fate-explosion-event = Раздается взрыв! +dice-of-fate-disease-event = { $user } заражается неизвестным вирусом! +dice-of-fate-nothing-event = { $user } не проиграл, он не захотел выигрывать! +dice-of-fate-cookie-event = Печенье появляется прямо из воздуха! +dice-of-fate-rejuvenate-event = Даже врачи завидуют здоровью { $user }! +dice-of-fate-money-event = Что нельзя купить за деньги? +dice-of-fate-revolver-event = Сыграем в рулетку? +dice-of-fate-magic-wand-event = Магия освещает путь { $user }! +dice-of-fate-slave-event = К { $user } скоро прибудет верный слуга! +dice-of-fate-random-syndie-bundle-event = Таинственная коробка появляется из ниоткуда! +dice-of-fate-full-access-event = "Ни одна дверь не устоит перед { $user }!" +dice-of-fate-damage-resist-event = " { $user } не чувствует боли!" +dice-of-fate-changeling-transformation-event = Происходит нечто невероятное! + +## Slave event role + +dice-of-fate-slave-role-name = Книжный червь +dice-of-fate-slave-role-description = Волшебным образом появившийся в этом мире слуга. +dice-of-fate-slave-server-message = Вы были призваны из другого измерения с единственной целью - служить { $user }. Выполняйте любые его приказы, охраняйте и защищайте его, теперь он ваш хозяин. + +## Dice names and descriptions + +ent-DiceOfFate = Кости судьбы + .desc = { "Игральная кость с 20 гранями. Каждая грань немного отличается от всех, но в чем же её отличие?" } + +ent-E20Dice = E20 + .desc = { "Игральная кость с 20 гранями. На одной из граней есть кнопка и таймер." } + +ent-BrokenDice = Часть игральной кости + .desc = { "Потемневший обломок двадцатигранника. Игра окончена?" } + diff --git a/Resources/Prototypes/Entities/Objects/Fun/dice.yml b/Resources/Prototypes/Entities/Objects/Fun/dice.yml index 852a1c2699c..54db3ea3099 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/dice.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/dice.yml @@ -131,3 +131,61 @@ types: Piercing: 5 # I love this + +- type: entity + parent: BaseItem + id: DiceOfFate + name: Dice Of Fate + description: A die with twenty sides. Each side is slightly different but in what way? + components: + - type: E20 + sides: 20 + currentValue: 20 + diceType: DiceOfFate + - type: Sprite + sprite: Objects/Fun/dice.rsi + state: d20_20 + noRot: true + - type: Item + size: Tiny + - type: TypingIndicator + proto: robot + - type: Speech + speechVerb: Robotic + speechSounds: Vending + - type: VoiceOfGod + +- type: entity + parent: BaseItem + id: E20Dice + name: E20 + description: A die with twenty sides. It has a button with a timer. + components: + - type: E20 + sides: 20 + currentValue: 20 + diceType: E20 + - type: Sprite + sprite: Objects/Fun/dice.rsi + state: d20_20 + noRot: true + - type: Item + size: Tiny + - type: TypingIndicator + proto: robot + - type: Speech + speechVerb: Robotic + speechSounds: Vending + - type: VoiceOfGod + +- type: entity + parent: BaseItem + id: BrokenDice + name: Broken Dice + description: Dice that's lost its powers, maybe there's still something in it. + components: + - type: Sprite + sprite: Objects/Fun/dice.rsi + state: dice_of_fate_used + - type: Item + size: Tiny diff --git a/Resources/Prototypes/Polymorphs/admin.yml b/Resources/Prototypes/Polymorphs/admin.yml index cb274ec7d43..29cc24308b0 100644 --- a/Resources/Prototypes/Polymorphs/admin.yml +++ b/Resources/Prototypes/Polymorphs/admin.yml @@ -47,3 +47,8 @@ forced: true inventory: Drop allowRepeatedMorphs: true + +- type: polymorph + id: DiceShard + configuration: + entity: BrokenDice diff --git a/Resources/Textures/Objects/Fun/dice.rsi/dice_of_fate_used.png b/Resources/Textures/Objects/Fun/dice.rsi/dice_of_fate_used.png new file mode 100644 index 0000000000000000000000000000000000000000..e156cf8f4338babd3c4d7983f6ef5beaf650ed38 GIT binary patch literal 294 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}4?JBQLn2y} z6C_v{Cy4Yk1sZU*Nkyz&^kx36XNHrqD}T(bR(W}pbw)?vmcpdt|0^Ot{%>-7#be;3 z>u^C_TD|N~{PoM{9~?c`tLWYvpdi8Yy6V@%oRs;+PnH?x%(>xMSf!xFwdcl8$!&lC zoZ9f^hvg3CI-hw*4;*0d6rZBv)5I6? Date: Sat, 4 May 2024 15:29:07 +0300 Subject: [PATCH 2/6] finally --- Content.Server/E20/E20System.Events.cs | 4 --- Content.Server/E20/E20System.cs | 2 +- .../Locale/en-US/store/uplink-catalog.ftl | 6 ++++ .../Locale/ru-RU/store/uplink-catalog.ftl | 6 ++++ .../Prototypes/Catalog/uplink_catalog.yml | 30 +++++++++++++++++++ 5 files changed, 43 insertions(+), 5 deletions(-) diff --git a/Content.Server/E20/E20System.Events.cs b/Content.Server/E20/E20System.Events.cs index 3f933381ee8..61d093ddee9 100644 --- a/Content.Server/E20/E20System.Events.cs +++ b/Content.Server/E20/E20System.Events.cs @@ -9,7 +9,6 @@ using Content.Server.Fluids.EntitySystems; using Content.Server.Ghost.Roles; using Content.Server.Ghost.Roles.Components; -using Content.Server.Mind; using Content.Server.Polymorph.Systems; using Content.Server.Revenant.Components; using Content.Shared.Access; @@ -31,8 +30,6 @@ using Content.Shared.Popups; using Content.Shared.Throwing; using Robust.Server.GameObjects; -using Robust.Shared.Audio.Systems; -using Robust.Shared.Configuration; using Robust.Shared.Prototypes; using Robust.Shared.Random; @@ -59,7 +56,6 @@ public sealed class E20SystemEvents : EntitySystem [Dependency] private readonly ChangelingRuleSystem _changelingRule = default!; [Dependency] private readonly SharedMindSystem _minds = default!; [Dependency] private readonly IEntityManager _entManager = default!; - [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly ThrowingSystem _throwingSystem = default!; [Dependency] private readonly TransformSystem _transform = default!; diff --git a/Content.Server/E20/E20System.cs b/Content.Server/E20/E20System.cs index 58c3ebc4280..eb590190ff4 100644 --- a/Content.Server/E20/E20System.cs +++ b/Content.Server/E20/E20System.cs @@ -64,7 +64,7 @@ private void DiceOfFatePicker(EntityUid uid, E20Component comp) events[20] = _events.ChangelingTransformationEvent; - EventsDelegate method = events[20]; + EventsDelegate method = events[comp.CurrentValue]; method(uid, comp); if (comp.IsUsed) diff --git a/Resources/Locale/en-US/store/uplink-catalog.ftl b/Resources/Locale/en-US/store/uplink-catalog.ftl index 6d71e064153..1781519474d 100644 --- a/Resources/Locale/en-US/store/uplink-catalog.ftl +++ b/Resources/Locale/en-US/store/uplink-catalog.ftl @@ -293,6 +293,12 @@ uplink-disposable-turret-desc = Looks and functions like a normal electrical too uplink-cluster-banana-peel-name = Cluster Banana uplink-cluster-banana-peel-desc = Splits into 6 explosive banana peels after being thrown, the peels detonate automatically after 20 seconds if nobody slips on them. +uplink-e20-name = E20 +uplink-e20-desc = The mysterious twenty-sided die triggers an explosion three seconds after activation, with the radius depending on the force of the throw. Don't succumb to the temptation of using it thoughtlessly, as the consequences could be irreversible. + +uplink-dice-of-fate-name = Dice of fate +uplink-dice-of-fate-desc = A dice concealing many secrets. Only your luck will be with you when you activate the twenty-sided. Each facet contains its own effect, from the most negative to the incredible. Use with caution! + # Armor uplink-chameleon-name = Chameleon Kit uplink-chameleon-desc = A backpack full of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more! diff --git a/Resources/Locale/ru-RU/store/uplink-catalog.ftl b/Resources/Locale/ru-RU/store/uplink-catalog.ftl index 32749b0a620..bee1a2a35b4 100644 --- a/Resources/Locale/ru-RU/store/uplink-catalog.ftl +++ b/Resources/Locale/ru-RU/store/uplink-catalog.ftl @@ -304,6 +304,12 @@ uplink-disposable-turret-desc = Выглядит и функционирует uplink-cluster-banana-peel-name = Кластерный банан uplink-cluster-banana-peel-desc = После броска разделяется на 6 взрывоопасных банановых кожурок, которые автоматически детонируют через 20 секунд, если на них никто не поскользнется. +uplink-e20-name = Е20 +uplink-e20-desc = Таинственный двадцатигранник, через три секунды после активации происходит взрыв, радиус которого зависит от силы броска. Не поддавайтесь соблазну бездумно использовать его, так как последствия могут оказаться необратимыми. + +uplink-dice-of-fate-name = Кости судьбы +uplink-dice-of-fate-desc = Игральная кость таящая в себе множество тайн. Только ваша удача будет рядом с вами когда вы активируете двадцатигранник. Каждая грань содержит свой эффект, от самых негативных до невероятных. Используйте с осторожностью! + # Armor uplink-chameleon-name = Набор хамелеона uplink-chameleon-desc = Рюкзак, полный предметов-хамелеонов, позволяющую вам маскироваться их под практически все, что есть на станции, и даже больше! diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index 1bc9117ae16..91f947d7339 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -1714,3 +1714,33 @@ - ResearchDirector - Chef - ResearchAssistant + +- type: listing + id: UplinkE20 + name: uplink-e20-name + description: uplink-e20-desc + icon: { sprite: Objects/Fun/dice.rsi, state: d20_20 } + productEntity: E20Dice + cost: + Telecrystal: 10 + categories: + - UplinkJob + conditions: + - !type:BuyerJobCondition # We can't use BuyerDepartmentCondition here since Zookeeper and Chef can also get this + whitelist: + - Librarian + +- type: listing + id: UplinkDiceOfFate + name: uplink-dice-of-fate-name + description: uplink-dice-of-fate-desc + icon: { sprite: Objects/Fun/dice.rsi, state: d20_1 } + productEntity: DiceOfFate + cost: + Telecrystal: 16 + categories: + - UplinkJob + conditions: + - !type:BuyerJobCondition # We can't use BuyerDepartmentCondition here since Zookeeper and Chef can also get this + whitelist: + - Librarian From 542329e28cf81abe7381cb612acde3d50ec772b4 Mon Sep 17 00:00:00 2001 From: grach Date: Thu, 16 May 2024 23:32:47 +0300 Subject: [PATCH 3/6] oleg fixes v1 --- Content.Server/E20/E20System.Events.cs | 53 +++++++++---------- Content.Server/E20/E20System.cs | 72 +++++++++++++------------- Content.Shared/E20/E20Component.cs | 10 +--- 3 files changed, 62 insertions(+), 73 deletions(-) diff --git a/Content.Server/E20/E20System.Events.cs b/Content.Server/E20/E20System.Events.cs index 61d093ddee9..a9ba643c8f3 100644 --- a/Content.Server/E20/E20System.Events.cs +++ b/Content.Server/E20/E20System.Events.cs @@ -35,39 +35,36 @@ namespace Content.Server.E20; -public sealed class E20SystemEvents : EntitySystem +public partial class E20System { [Dependency] private readonly ExplosionSystem _explosion = default!; [Dependency] private readonly BodySystem _bodySystem = default!; [Dependency] private readonly DamageableSystem _damageableSystem = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly InventorySystem _inventory = default!; - [Dependency] private readonly PolymorphSystem _polymorphSystem = default!; [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!; [Dependency] private readonly StaminaSystem _stamina = default!; - [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly RejuvenateSystem _rejuvenate = default!; [Dependency] private readonly GhostRoleSystem _ghost = default!; [Dependency] private readonly MetaDataSystem _metaData = default!; - [Dependency] private readonly IChatManager _chat = default!; + [Dependency] private readonly IChatManager _ichat = default!; [Dependency] private readonly SharedAccessSystem _accessSystem = default!; [Dependency] private readonly SmokeSystem _smoke = default!; [Dependency] private readonly DamageableSystem _damageable = default!; [Dependency] private readonly ChangelingRuleSystem _changelingRule = default!; [Dependency] private readonly SharedMindSystem _minds = default!; [Dependency] private readonly IEntityManager _entManager = default!; - [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly ThrowingSystem _throwingSystem = default!; [Dependency] private readonly TransformSystem _transform = default!; - public override void Initialize() + public void InitializeEvents() { IoCManager.Register(); base.Initialize(); SubscribeLocalEvent(OnTake); } - public void ExplosionEvent(EntityUid uid, E20Component comp) + private void ExplosionEvent(EntityUid uid, E20Component comp) { float intensity = comp.CurrentValue * 480; // Calculating power of explosion var coords = _transform.GetMapCoordinates(uid); @@ -90,14 +87,14 @@ public void ExplosionEvent(EntityUid uid, E20Component comp) intensity, 5, 240); } - public void FullDestructionEvent(EntityUid uid, E20Component comp) + private void FullDestructionEvent(EntityUid uid, E20Component comp) { _popup.PopupCoordinates(Loc.GetString("dice-of-fate-full-destruction-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); _bodySystem.GibBody(comp.LastUser); } - public void DieEvent(EntityUid uid, E20Component comp) + private void DieEvent(EntityUid uid, E20Component comp) { var damage = new DamageSpecifier(_prototypeManager.Index("Slash"), 200); @@ -106,7 +103,7 @@ public void DieEvent(EntityUid uid, E20Component comp) _damageableSystem.TryChangeDamage(comp.LastUser, damage, true); } - public void AngryMobsSpawnEvent(EntityUid uid, E20Component comp) + private void AngryMobsSpawnEvent(EntityUid uid, E20Component comp) { var coords = _transform.GetMapCoordinates(uid); @@ -115,12 +112,13 @@ public void AngryMobsSpawnEvent(EntityUid uid, E20Component comp) EntityManager.SpawnEntities(coords, "MobCarpDungeon", 5); } - public void ItemsDestructionEvent(EntityUid uid, E20Component comp) + private void ItemsDestructionEvent(EntityUid uid, E20Component comp) { var bodyId = comp.LastUser; if (!TryComp(comp.LastUser, out var inventory)) return; + foreach (var item in _inventory.GetHandOrInventoryEntities(bodyId)) { QueueDel(item); @@ -130,14 +128,14 @@ public void ItemsDestructionEvent(EntityUid uid, E20Component comp) ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); } - public void MonkeyPolymorphEvent(EntityUid uid, E20Component comp) + private void MonkeyPolymorphEvent(EntityUid uid, E20Component comp) { _popup.PopupCoordinates(Loc.GetString("dice-of-fate-monkey-polymorph-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); _polymorphSystem.PolymorphEntity(comp.LastUser, "AdminMonkeySmite"); } - public void SpeedReduceEvent(EntityUid uid, E20Component comp) + private void SpeedReduceEvent(EntityUid uid, E20Component comp) { if (!TryComp(comp.LastUser, out var movementSpeed)) return; @@ -155,7 +153,7 @@ public void SpeedReduceEvent(EntityUid uid, E20Component comp) ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); } - public void ThrowingEvent(EntityUid uid, E20Component comp) + private void ThrowingEvent(EntityUid uid, E20Component comp) { var diceCoords = _transform.GetMapCoordinates(uid); var playerCoords = _transform.GetMapCoordinates(comp.LastUser); @@ -177,7 +175,7 @@ public void ThrowingEvent(EntityUid uid, E20Component comp) _stamina.TakeStaminaDamage(comp.LastUser, staminaComponent.CritThreshold); } - public void DiseaseEvent(EntityUid uid, E20Component comp) + private void DiseaseEvent(EntityUid uid, E20Component comp) { _popup.PopupCoordinates(Loc.GetString("dice-of-fate-disease-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); @@ -185,13 +183,13 @@ public void DiseaseEvent(EntityUid uid, E20Component comp) blight.Duration = 0f; } - public void NothingEvent(EntityUid uid, E20Component comp) + private void NothingEvent(EntityUid uid, E20Component comp) { _popup.PopupCoordinates(Loc.GetString("dice-of-fate-nothing-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); } - public void CookieEvent(EntityUid uid, E20Component comp) + private void CookieEvent(EntityUid uid, E20Component comp) { var coords = _transform.GetMapCoordinates(uid); @@ -200,14 +198,14 @@ public void CookieEvent(EntityUid uid, E20Component comp) EntityManager.SpawnEntities(coords, "FoodBakedCookie", 2); } - public void RejuvenateEvent(EntityUid uid, E20Component comp) + private void RejuvenateEvent(EntityUid uid, E20Component comp) { _popup.PopupCoordinates(Loc.GetString("dice-of-fate-rejuvenate-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); _rejuvenate.PerformRejuvenate(comp.LastUser); } - public void MoneyEvent(EntityUid uid, E20Component comp) + private void MoneyEvent(EntityUid uid, E20Component comp) { var coords = _transform.GetMapCoordinates(uid); @@ -216,7 +214,7 @@ public void MoneyEvent(EntityUid uid, E20Component comp) EntityManager.SpawnEntities(coords, "SpaceCash1000", 5); } - public void RevolverEvent(EntityUid uid, E20Component comp) + private void RevolverEvent(EntityUid uid, E20Component comp) { var coords = _transform.GetMapCoordinates(uid); @@ -225,7 +223,7 @@ public void RevolverEvent(EntityUid uid, E20Component comp) EntityManager.SpawnEntities(coords, "WeaponRevolverInspector", 1); } - public void MagicWandEvent(EntityUid uid, E20Component comp) + private void MagicWandEvent(EntityUid uid, E20Component comp) { List wands = new List() { @@ -247,8 +245,7 @@ public void MagicWandEvent(EntityUid uid, E20Component comp) EntityManager.SpawnEntities(coords, roll, 1); } - - public void SlaveEvent(EntityUid uid, E20Component comp) + private void SlaveEvent(EntityUid uid, E20Component comp) { var ghost = EnsureComp(uid); @@ -280,14 +277,14 @@ private void OnTake(EntityUid uid, GhostRoleComponent comp, TakeGhostRoleEvent a var newMind = _minds.CreateMind(args.Player.UserId, name); _minds.SetUserId(newMind, args.Player.UserId); _minds.TransferTo(newMind, mob); - _chat.DispatchServerMessage(args.Player,Loc.GetString("dice-of-fate-slave-server-message", + _ichat.DispatchServerMessage(args.Player,Loc.GetString("dice-of-fate-slave-server-message", ("user", Identity.Entity(e20.LastUser, _entManager)))); _ghost.UnregisterGhostRole((uid, ghost)); _polymorphSystem.PolymorphEntity(uid, "DiceShard"); } - public void RandomSyndieBundleEvent(EntityUid uid, E20Component comp) + private void RandomSyndieBundleEvent(EntityUid uid, E20Component comp) { List bundles = new List() { @@ -313,7 +310,7 @@ public void RandomSyndieBundleEvent(EntityUid uid, E20Component comp) EntityManager.SpawnEntities(coords, roll, 1); } - public void FullAccessEvent(EntityUid uid, E20Component comp) + private void FullAccessEvent(EntityUid uid, E20Component comp) { EnsureComp(comp.LastUser); var allAccess = _prototypeManager @@ -326,7 +323,7 @@ public void FullAccessEvent(EntityUid uid, E20Component comp) _accessSystem.TrySetTags(comp.LastUser, allAccess); } - public void DamageResistEvent(EntityUid uid, E20Component comp) + private void DamageResistEvent(EntityUid uid, E20Component comp) { var damageSet = "DiceOfFate"; @@ -335,7 +332,7 @@ public void DamageResistEvent(EntityUid uid, E20Component comp) _damageable.SetDamageModifierSetId(comp.LastUser, damageSet); } - public void ChangelingTransformationEvent(EntityUid uid, E20Component comp) + private void ChangelingTransformationEvent(EntityUid uid, E20Component comp) { if (!TryComp(comp.LastUser, out var targetMindComp)) return; diff --git a/Content.Server/E20/E20System.cs b/Content.Server/E20/E20System.cs index eb590190ff4..162f010db2d 100644 --- a/Content.Server/E20/E20System.cs +++ b/Content.Server/E20/E20System.cs @@ -1,9 +1,6 @@ -using System.Reflection; -using Content.Server.Body.Systems; -using Content.Server.Chat.Systems; +using Content.Server.Chat.Systems; using Content.Server.Explosion.EntitySystems; using Content.Server.Polymorph.Systems; -using Content.Shared.CCVar; using Content.Shared.E20; using Content.Shared.Explosion.Components; using Content.Shared.Popups; @@ -12,66 +9,69 @@ namespace Content.Server.E20; - -public sealed class E20System : SharedE20System +public partial class E20System : SharedE20System { [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly ChatSystem _chat = default!; [Dependency] private readonly TriggerSystem _triggerSystem = default!; - [Dependency] private readonly E20SystemEvents _events = default!; [Dependency] private readonly PolymorphSystem _polymorphSystem = default!; + private readonly List _eventsList = new(); + public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnTimerRemove); + Events(); + } + + private void Events() + { + _eventsList.Add(FullDestructionEvent); + _eventsList.Add(DieEvent); + _eventsList.Add(AngryMobsSpawnEvent); + _eventsList.Add(ItemsDestructionEvent); + _eventsList.Add(MonkeyPolymorphEvent); + _eventsList.Add(SpeedReduceEvent); + _eventsList.Add(ThrowingEvent); + _eventsList.Add(ExplosionEvent); + _eventsList.Add(DiseaseEvent); + _eventsList.Add(NothingEvent); + _eventsList.Add(CookieEvent); + _eventsList.Add(RejuvenateEvent); + _eventsList.Add(MoneyEvent); + _eventsList.Add(RevolverEvent); + _eventsList.Add(MagicWandEvent); + _eventsList.Add(SlaveEvent); + _eventsList.Add(RandomSyndieBundleEvent); + _eventsList.Add(FullAccessEvent); + _eventsList.Add(DamageResistEvent); + _eventsList.Add(ChangelingTransformationEvent); } private delegate void EventsDelegate(EntityUid uid, E20Component comp); private void E20Picker(EntityUid uid, E20Component comp) { - _events.ExplosionEvent(uid, comp); + ExplosionEvent(uid, comp); _polymorphSystem.PolymorphEntity(uid, "DiceShard"); } private void DiceOfFatePicker(EntityUid uid, E20Component comp) { comp.IsUsed = true; - //FIXME - Dictionary events = new Dictionary(); - events[1] = _events.FullDestructionEvent; - events[2] = _events.DieEvent; - events[3] = _events.AngryMobsSpawnEvent; - events[4] = _events.ItemsDestructionEvent; - events[5] = _events.MonkeyPolymorphEvent; - events[6] = _events.SpeedReduceEvent; - events[7] = _events.ThrowingEvent; - events[8] = _events.ExplosionEvent; - events[9] = _events.DiseaseEvent; - events[10] = _events.NothingEvent; - events[11] = _events.CookieEvent; - events[12] = _events.RejuvenateEvent; - events[13] = _events.MoneyEvent; - events[14] = _events.RevolverEvent; - events[15] = _events.MagicWandEvent; - events[16] = _events.SlaveEvent; - events[17] = _events.RandomSyndieBundleEvent; - events[18] = _events.FullAccessEvent; - events[19] = _events.DamageResistEvent; - events[20] = _events.ChangelingTransformationEvent; - - - EventsDelegate method = events[comp.CurrentValue]; - method(uid, comp); + + if (comp.CurrentValue > 0 && comp.CurrentValue <= _eventsList.Count) + { + _eventsList[comp.CurrentValue - 1]?.Invoke(uid, comp); + } if (comp.IsUsed) { _polymorphSystem.PolymorphEntity(uid, "DiceShard"); } - } private void OnTimerRemove(EntityUid uid, ActiveTimerTriggerComponent comp, ComponentRemove args) @@ -83,7 +83,6 @@ private void OnTimerRemove(EntityUid uid, ActiveTimerTriggerComponent comp, Comp E20Component e20 = EntityManager.GetComponent(uid); - if (e20.DiceType == "E20") { E20Picker(uid, e20); @@ -118,6 +117,5 @@ protected override void Roll(EntityUid uid, E20Component? die = null) _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/E20/E20Component.cs b/Content.Shared/E20/E20Component.cs index 85d36f8b4f9..e9661e7bc29 100644 --- a/Content.Shared/E20/E20Component.cs +++ b/Content.Shared/E20/E20Component.cs @@ -22,12 +22,8 @@ public sealed partial class E20Component : Component public EntityUid LastUser; - //[DataField] - //[AutoNetworkedField] - //public List Events = new(); - - [DataField] - public string DiceType { get; set; } + [DataField(required: true)] + public string DiceType { get; set; } = "E20"; /// /// Delay for dice action(Gib or Explosion). @@ -67,6 +63,4 @@ public sealed partial class E20Component : Component [DataField] [AutoNetworkedField] public int CurrentValue { get; set; } = 20; - - } From 65a1675638c3d7bcacaca48be5ac870e20163879 Mon Sep 17 00:00:00 2001 From: grach Date: Fri, 17 May 2024 19:23:30 +0300 Subject: [PATCH 4/6] add logs --- Content.Server/E20/E20System.Events.cs | 70 ++++++++++++++++++++++++-- Resources/Locale/en-US/e20/events.ftl | 4 +- Resources/Locale/ru-RU/e20/events.ftl | 4 +- 3 files changed, 69 insertions(+), 9 deletions(-) diff --git a/Content.Server/E20/E20System.Events.cs b/Content.Server/E20/E20System.Events.cs index a9ba643c8f3..2d4e0e1cae0 100644 --- a/Content.Server/E20/E20System.Events.cs +++ b/Content.Server/E20/E20System.Events.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Numerics; using Content.Server.Administration.Commands; +using Content.Server.Administration.Logs; using Content.Server.Administration.Systems; using Content.Server.Body.Systems; using Content.Server.Changeling; @@ -19,6 +20,7 @@ using Content.Shared.Damage.Components; using Content.Shared.Damage.Prototypes; using Content.Shared.Damage.Systems; +using Content.Shared.Database; using Content.Shared.Dataset; using Content.Shared.E20; using Content.Shared.IdentityManagement; @@ -56,6 +58,7 @@ public partial class E20System [Dependency] private readonly IEntityManager _entManager = default!; [Dependency] private readonly ThrowingSystem _throwingSystem = default!; [Dependency] private readonly TransformSystem _transform = default!; + [Dependency] private readonly IAdminLogManager _adminLogger = default!; public void InitializeEvents() { @@ -83,6 +86,7 @@ private void ExplosionEvent(EntityUid uid, E20Component comp) _popup.PopupCoordinates(Loc.GetString("dice-of-fate-explosion-event"), Transform(uid).Coordinates, PopupType.Medium); + _explosion.QueueExplosion(coords, "DemolitionCharge", intensity, 5, 240); } @@ -91,6 +95,9 @@ private void FullDestructionEvent(EntityUid uid, E20Component comp) { _popup.PopupCoordinates(Loc.GetString("dice-of-fate-full-destruction-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} gibs {_entManager.ToPrettyString(comp.LastUser):target}"); + _bodySystem.GibBody(comp.LastUser); } @@ -100,6 +107,9 @@ private void DieEvent(EntityUid uid, E20Component comp) _popup.PopupCoordinates(Loc.GetString("dice-of-fate-die-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} kills {_entManager.ToPrettyString(comp.LastUser):target}"); + _damageableSystem.TryChangeDamage(comp.LastUser, damage, true); } @@ -109,6 +119,9 @@ private void AngryMobsSpawnEvent(EntityUid uid, E20Component comp) _popup.PopupCoordinates(Loc.GetString("dice-of-fate-angry-mobs-spawn-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} spawns angry carps"); + EntityManager.SpawnEntities(coords, "MobCarpDungeon", 5); } @@ -126,12 +139,17 @@ private void ItemsDestructionEvent(EntityUid uid, E20Component comp) _popup.PopupCoordinates(Loc.GetString("dice-of-fate-items-destruction-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} destroys {_entManager.ToPrettyString(comp.LastUser):target} items"); } private void MonkeyPolymorphEvent(EntityUid uid, E20Component comp) { _popup.PopupCoordinates(Loc.GetString("dice-of-fate-monkey-polymorph-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} transforms {_entManager.ToPrettyString(comp.LastUser):target} into a monkey"); + _polymorphSystem.PolymorphEntity(comp.LastUser, "AdminMonkeySmite"); } @@ -151,6 +169,8 @@ private void SpeedReduceEvent(EntityUid uid, E20Component comp) _popup.PopupCoordinates(Loc.GetString("dice-of-fate-speed-reduce-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} reduces {_entManager.ToPrettyString(comp.LastUser):target} speed"); } private void ThrowingEvent(EntityUid uid, E20Component comp) @@ -161,7 +181,7 @@ private void ThrowingEvent(EntityUid uid, E20Component comp) var direction = diceCoords.Position - playerCoords.Position; var randomizedDirection = direction + new Vector2(_random.Next(-10, 10), _random.Next(-10, 10)); - _throwingSystem.TryThrow(comp.LastUser, randomizedDirection, 60, uid); + _throwingSystem.TryThrow(comp.LastUser, randomizedDirection, 60); var damage = new DamageSpecifier(_prototypeManager.Index("Blunt"), 50); @@ -172,6 +192,9 @@ private void ThrowingEvent(EntityUid uid, E20Component comp) _popup.PopupCoordinates(Loc.GetString("dice-of-fate-throwing-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} throws and stuns {_entManager.ToPrettyString(comp.LastUser):target}"); + _stamina.TakeStaminaDamage(comp.LastUser, staminaComponent.CritThreshold); } @@ -179,6 +202,9 @@ private void DiseaseEvent(EntityUid uid, E20Component comp) { _popup.PopupCoordinates(Loc.GetString("dice-of-fate-disease-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} infects {_entManager.ToPrettyString(comp.LastUser):target} with disease"); + var blight = EnsureComp(comp.LastUser); blight.Duration = 0f; } @@ -187,6 +213,8 @@ private void NothingEvent(EntityUid uid, E20Component comp) { _popup.PopupCoordinates(Loc.GetString("dice-of-fate-nothing-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} do nothing"); } private void CookieEvent(EntityUid uid, E20Component comp) @@ -195,6 +223,9 @@ private void CookieEvent(EntityUid uid, E20Component comp) _popup.PopupCoordinates(Loc.GetString("dice-of-fate-cookie-event"), Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} spawns a cookie"); + EntityManager.SpawnEntities(coords, "FoodBakedCookie", 2); } @@ -202,6 +233,9 @@ private void RejuvenateEvent(EntityUid uid, E20Component comp) { _popup.PopupCoordinates(Loc.GetString("dice-of-fate-rejuvenate-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} heals {_entManager.ToPrettyString(comp.LastUser):target}"); + _rejuvenate.PerformRejuvenate(comp.LastUser); } @@ -211,6 +245,9 @@ private void MoneyEvent(EntityUid uid, E20Component comp) _popup.PopupCoordinates(Loc.GetString("dice-of-fate-money-event"), Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} spawns money"); + EntityManager.SpawnEntities(coords, "SpaceCash1000", 5); } @@ -220,7 +257,11 @@ private void RevolverEvent(EntityUid uid, E20Component comp) _popup.PopupCoordinates(Loc.GetString("dice-of-fate-revolver-event"), Transform(uid).Coordinates, PopupType.Medium); - EntityManager.SpawnEntities(coords, "WeaponRevolverInspector", 1); + + var spawned = EntityManager.SpawnEntities(coords, "WeaponRevolverInspector", 1); + + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} spawns a revolver {_entManager.ToPrettyString(spawned[0]):target}"); } private void MagicWandEvent(EntityUid uid, E20Component comp) @@ -242,7 +283,11 @@ private void MagicWandEvent(EntityUid uid, E20Component comp) _popup.PopupCoordinates(Loc.GetString("dice-of-fate-magic-wand-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); - EntityManager.SpawnEntities(coords, roll, 1); + + var spawned = EntityManager.SpawnEntities(coords, roll, 1); + + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} spawns magic wand {_entManager.ToPrettyString(spawned[0]):target}"); } private void SlaveEvent(EntityUid uid, E20Component comp) @@ -256,6 +301,9 @@ private void SlaveEvent(EntityUid uid, E20Component comp) _popup.PopupCoordinates(Loc.GetString("dice-of-fate-slave-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} creates a slave ghost role {ghost.RoleName}"); } private void OnTake(EntityUid uid, GhostRoleComponent comp, TakeGhostRoleEvent args) @@ -307,7 +355,11 @@ private void RandomSyndieBundleEvent(EntityUid uid, E20Component comp) _popup.PopupCoordinates(Loc.GetString("dice-of-fate-random-syndie-bundle-event"), Transform(uid).Coordinates, PopupType.Medium); - EntityManager.SpawnEntities(coords, roll, 1); + + var spawned = EntityManager.SpawnEntities(coords, roll, 1); + + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} spawns a syndie bundle {_entManager.ToPrettyString(spawned[0]):target}"); } private void FullAccessEvent(EntityUid uid, E20Component comp) @@ -317,9 +369,11 @@ private void FullAccessEvent(EntityUid uid, E20Component comp) .EnumeratePrototypes() .Select(p => new ProtoId(p.ID)).ToArray(); - _popup.PopupCoordinates(Loc.GetString("dice-of-fate-full-access-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} gives to {_entManager.ToPrettyString(comp.LastUser):target} full access"); + _accessSystem.TrySetTags(comp.LastUser, allAccess); } @@ -329,6 +383,9 @@ private void DamageResistEvent(EntityUid uid, E20Component comp) _popup.PopupCoordinates(Loc.GetString("dice-of-fate-damage-resist-event", ("user", Identity.Entity(comp.LastUser, _entManager))) , Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} gives to {_entManager.ToPrettyString(comp.LastUser):target} damage resistance"); + _damageable.SetDamageModifierSetId(comp.LastUser, damageSet); } @@ -342,6 +399,9 @@ private void ChangelingTransformationEvent(EntityUid uid, E20Component comp) _popup.PopupCoordinates(Loc.GetString("dice-of-fate-changeling-transformation-event"), Transform(uid).Coordinates, PopupType.Medium); + _adminLogger.Add(LogType.Action, + $"{_entManager.ToPrettyString(uid):user} transforms {_entManager.ToPrettyString(comp.LastUser):target} into changeling"); + _changelingRule.MakeChangeling(comp.LastUser, new ChangelingRuleComponent(), false); } } diff --git a/Resources/Locale/en-US/e20/events.ftl b/Resources/Locale/en-US/e20/events.ftl index 068db242b46..d2de5d7303c 100644 --- a/Resources/Locale/en-US/e20/events.ftl +++ b/Resources/Locale/en-US/e20/events.ftl @@ -17,7 +17,7 @@ dice-of-fate-revolver-event = Shall we play roulette? dice-of-fate-magic-wand-event = Magic lights the way { $user }! dice-of-fate-slave-event = A faithful servant is coming to { $user } soon! dice-of-fate-random-syndie-bundle-event = Mysterious box appears out of nowhere! -dice-of-fate-full-access-event = No door can resist {$user}! +dice-of-fate-full-access-event = No door can resist { $user }! dice-of-fate-damage-resist-event = { $user } feels no pain! dice-of-fate-changeling-transformation-event = Something incredible is happening! @@ -25,4 +25,4 @@ dice-of-fate-changeling-transformation-event = Something incredible is happening dice-of-fate-slave-role-name = Bookworm dice-of-fate-slave-role-description = A servant who magically appeared in this world. -dice-of-fate-slave-server-message = You were called from another dimension for the sole purpose of serving {$user}. Follow any of his orders, guard and protect him, now he is your master. +dice-of-fate-slave-server-message = You were called from another dimension for the sole purpose of serving { $user }. Follow any of his orders, guard and protect him, now he is your master. diff --git a/Resources/Locale/ru-RU/e20/events.ftl b/Resources/Locale/ru-RU/e20/events.ftl index 8dc3e62b3a0..b204a002314 100644 --- a/Resources/Locale/ru-RU/e20/events.ftl +++ b/Resources/Locale/ru-RU/e20/events.ftl @@ -17,8 +17,8 @@ dice-of-fate-revolver-event = Сыграем в рулетку? dice-of-fate-magic-wand-event = Магия освещает путь { $user }! dice-of-fate-slave-event = К { $user } скоро прибудет верный слуга! dice-of-fate-random-syndie-bundle-event = Таинственная коробка появляется из ниоткуда! -dice-of-fate-full-access-event = "Ни одна дверь не устоит перед { $user }!" -dice-of-fate-damage-resist-event = " { $user } не чувствует боли!" +dice-of-fate-full-access-event = Ни одна дверь не устоит перед { $user }! +dice-of-fate-damage-resist-event = { $user } не чувствует боли! dice-of-fate-changeling-transformation-event = Происходит нечто невероятное! ## Slave event role From 82ffadd5e65abc3d5561a0d002f1273bef09b420 Mon Sep 17 00:00:00 2001 From: grach Date: Fri, 17 May 2024 21:18:42 +0300 Subject: [PATCH 5/6] hailrake s system --- Content.Server/E20/E20System.Events.cs | 2 +- .../_Lfwb/PredictedRandom/PredictedRandom.cs | 106 ++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 Content.Shared/_Lfwb/PredictedRandom/PredictedRandom.cs diff --git a/Content.Server/E20/E20System.Events.cs b/Content.Server/E20/E20System.Events.cs index 2d4e0e1cae0..78fe1a0de9d 100644 --- a/Content.Server/E20/E20System.Events.cs +++ b/Content.Server/E20/E20System.Events.cs @@ -401,7 +401,7 @@ private void ChangelingTransformationEvent(EntityUid uid, E20Component comp) Transform(uid).Coordinates, PopupType.Medium); _adminLogger.Add(LogType.Action, $"{_entManager.ToPrettyString(uid):user} transforms {_entManager.ToPrettyString(comp.LastUser):target} into changeling"); - + _changelingRule.MakeChangeling(comp.LastUser, new ChangelingRuleComponent(), false); } } diff --git a/Content.Shared/_Lfwb/PredictedRandom/PredictedRandom.cs b/Content.Shared/_Lfwb/PredictedRandom/PredictedRandom.cs new file mode 100644 index 00000000000..47886139c87 --- /dev/null +++ b/Content.Shared/_Lfwb/PredictedRandom/PredictedRandom.cs @@ -0,0 +1,106 @@ +using Robust.Shared.Random; +using Robust.Shared.Timing; +using Robust.Shared.Utility; + +namespace Content.Shared._Lfwb.PredictedRandom; + +public sealed class PredictedRandomSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + + private System.Random _random = new(); + + #region Roll + + private int Roll(int sides) + { + return _random.Next(1, sides + 1); + } + + public int RollWith(int sides, int numberOfDice) + { + SetSeed(); + + var total = 0; + for (var i = 0; i < numberOfDice; i++) + { + total += Roll(sides); + } + + return total; + } + + #endregion + + #region Next + + public int Next(int minValue, int maxValue) + { + SetSeed(); + return _random.Next(minValue, maxValue); + } + + public int Next(int minValue, int maxValue, int value) + { + SetSeed(value); + return _random.Next(minValue, maxValue); + } + + public double NextDouble() + { + SetSeed(); + return _random.NextDouble(); + } + + public float NextFloat(float minValue, float maxValue) + { + SetSeed(); + return _random.NextFloat() * (maxValue - minValue) + minValue; + } + + #endregion + + #region Prob + + public bool Prob(float chance) + { + DebugTools.Assert(chance <= 1 && chance >= 0, $"Chance must be in the range 0-1. It was {chance}."); + + SetSeed(); + return _random.NextDouble() < chance; + } + + #endregion + + #region Pick + + public T Pick(IReadOnlyList list) + { + SetSeed(); + + var index = _random.Next(list.Count); + return list[index]; + } + + #endregion + + #region Private + + private void SetSeed() + { + var currentTick = _timing.CurTime.Milliseconds.GetHashCode(); + _random = new System.Random(currentTick); + } + + private void SetSeed(int value) + { + var currentTick = _timing.CurTime.Milliseconds.GetHashCode(); + var valueHash = value.GetHashCode(); + + var hash = HashCode.Combine(currentTick, valueHash); + + _random = new System.Random(hash); + } + + #endregion +} From 1681e447f11ca9ff088761f513c1ed4ac7fd4fcf Mon Sep 17 00:00:00 2001 From: grach Date: Thu, 30 May 2024 17:22:58 +0300 Subject: [PATCH 6/6] may i swap branches please --- Content.Server/E20/E20System.cs | 4 ++-- Content.Shared/E20/E20Component.cs | 1 + Content.Shared/E20/SharedE20System.cs | 24 ++++++++++++++++++------ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Content.Server/E20/E20System.cs b/Content.Server/E20/E20System.cs index 162f010db2d..f84a48680a7 100644 --- a/Content.Server/E20/E20System.cs +++ b/Content.Server/E20/E20System.cs @@ -106,7 +106,7 @@ protected override void TimerEvent(EntityUid uid, E20Component? die = null) _chat.TrySendInGameICMessage(uid, Loc.GetString("DIE"), InGameICChatType.Speak, true); } - protected override void Roll(EntityUid uid, E20Component? die = null) + /*protected override void Roll(EntityUid uid, E20Component? die = null) { if (!Resolve(uid, ref die)) return; @@ -116,6 +116,6 @@ protected override void Roll(EntityUid uid, E20Component? die = null) _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/E20/E20Component.cs b/Content.Shared/E20/E20Component.cs index e9661e7bc29..ee697d436b5 100644 --- a/Content.Shared/E20/E20Component.cs +++ b/Content.Shared/E20/E20Component.cs @@ -12,6 +12,7 @@ public sealed partial class E20Component : Component /// Or rolling value of dice again after activation. /// + [AutoNetworkedField] public bool IsActivated = false; public bool IsUsed = false; diff --git a/Content.Shared/E20/SharedE20System.cs b/Content.Shared/E20/SharedE20System.cs index 952eb91677c..ea7cee33837 100644 --- a/Content.Shared/E20/SharedE20System.cs +++ b/Content.Shared/E20/SharedE20System.cs @@ -1,10 +1,16 @@ -using Content.Shared.Interaction.Events; +using Content.Shared._Lfwb.PredictedRandom; +using Content.Shared.Interaction.Events; +using Content.Shared.Popups; using Content.Shared.Throwing; +using Robust.Shared.Audio.Systems; namespace Content.Shared.E20; public abstract class SharedE20System : EntitySystem { + [Dependency] private readonly PredictedRandomSystem _predictedRandom = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; public override void Initialize() { base.Initialize(); @@ -29,8 +35,6 @@ private void OnUseInHand(EntityUid uid, E20Component component , UseInHandEvent component.IsActivated = true; component.LastUser = args.User; TimerEvent(uid, component); - - } private void OnLand(EntityUid uid, E20Component component, ref LandEvent args) @@ -69,10 +73,18 @@ protected virtual void TimerEvent(EntityUid uid, E20Component? die = null) // See the server system, client cannot count ¯\_(ツ)_/¯. } - protected virtual void Roll(EntityUid uid, E20Component? die = null) + private void Roll(EntityUid uid, E20Component? die = null) { - // See the server system, client cannot predict rolling. - } + if (!Resolve(uid, ref die)) + return; + + if (die.IsActivated) + return; + var roll = _predictedRandom.Next(1, die.Sides); + SetCurrentSide(uid, roll, die); + _popup.PopupEntity(Loc.GetString("dice-component-on-roll-land", ("die", uid), ("currentSide", die.CurrentValue)), uid); + _audio.PlayPvs(die.Sound, uid); + } }