public void RefreshTimer(EntityUid uid, bool minimumBound = true, AdvertiseComponent?advertise = null) { if (!Resolve(uid, ref advertise)) { return; } var minWait = Math.Max(1, advertise.MinimumWait); var maxWait = Math.Max(minWait, advertise.MaximumWait); var waitSeconds = minimumBound ? _random.Next(minWait, maxWait) : _random.Next(maxWait); advertise.NextAdvertisementTime = _gameTiming.CurTime.Add(TimeSpan.FromSeconds(waitSeconds)); }
private void OnClugUse(EntityUid uid, ClusterGrenadeComponent component, UseInHandEvent args) { if (component.CountDown || (component.GrenadesContainer.ContainedEntities.Count + component.UnspawnedCount) <= 0) { return; } // TODO: Should be an Update loop uid.SpawnTimer((int)(component.Delay * 1000), () => { if (Deleted(component.Owner)) { return; } component.CountDown = true; var delay = 20; var grenadesInserted = component.GrenadesContainer.ContainedEntities.Count + component.UnspawnedCount; var thrownCount = 0; var segmentAngle = 360 / grenadesInserted; while (TryGetGrenade(component, out var grenade)) { var angleMin = segmentAngle * thrownCount; var angleMax = segmentAngle * (thrownCount + 1); var angle = Angle.FromDegrees(_random.Next(angleMin, angleMax)); // var distance = random.NextFloat() * _throwDistance; delay += _random.Next(550, 900); thrownCount++; // TODO: Suss out throw strength grenade.TryThrow(angle.ToVec().Normalized *component.ThrowDistance); grenade.SpawnTimer(delay, () => { if ((!EntityManager.EntityExists(grenade) ? EntityLifeStage.Deleted : MetaData(grenade).EntityLifeStage) >= EntityLifeStage.Deleted) { return; } _trigger.Trigger(grenade, args.User); }); } EntityManager.DeleteEntity(uid); }); args.Handled = true; }
private void DoSpawn(IEntity owner, IRobustRandom random) { if (Spawn == null) { return; } foreach (var(key, value) in Spawn) { var count = value.Min >= value.Max ? value.Min : random.Next(value.Min, value.Max + 1); if (count == 0) { continue; } if (EntityPrototypeHelpers.HasComponent <StackComponent>(key)) { var spawned = owner.EntityManager.SpawnEntity(key, owner.Transform.Coordinates); var stack = spawned.GetComponent <StackComponent>(); stack.Count = count; spawned.RandomOffset(0.5f); } else { for (var i = 0; i < count; i++) { var spawned = owner.EntityManager.SpawnEntity(key, owner.Transform.Coordinates); spawned.RandomOffset(0.5f); } } } }
async Task <bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs) { if (!_powerReceiver?.Powered ?? false) { return(false); } if (eventArgs.Using.TryGetComponent(out ProduceComponent? produce) && produce.Seed != null) { eventArgs.User.PopupMessageCursor(Loc.GetString("seed-extractor-component-interact-message", ("name", eventArgs.Using.Name))); eventArgs.Using.QueueDelete(); var random = _random.Next(_minSeeds, _maxSeeds); for (var i = 0; i < random; i++) { produce.Seed.SpawnSeedPacket(Owner.Transform.Coordinates, Owner.EntityManager); } return(true); } return(false); }
public void Play(ScheduledSound schedule) { if (!schedule.Play) { return; } Timer.Spawn((int)schedule.Delay + (_random.Next((int)schedule.RandomDelay)), () => { if (!schedule.Play) { return; // We make sure this hasn't changed. } if (_audioSystem == null) { _audioSystem = EntitySystem.Get <AudioSystem>(); } _audioStreams.Add(schedule, _audioSystem.Play(schedule.Filename, Owner, schedule.AudioParams)); if (schedule.Times == 0) { return; } if (schedule.Times > 0) { schedule.Times--; } Play(schedule); }); }
private void OnPlaqueMapInit(EntityUid uid, AtmosPlaqueComponent component, MapInitEvent args) { var rand = _random.Next(100); // Let's not pat ourselves on the back too hard. // 1% chance of zumos if (rand == 0) { component.Type = PlaqueType.Zumos; } // 9% FEA else if (rand <= 10) { component.Type = PlaqueType.Fea; } // 45% ZAS else if (rand <= 55) { component.Type = PlaqueType.Zas; } // 45% LINDA else { component.Type = PlaqueType.Linda; } UpdateSign(component); }
async Task <bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs) { if (!_entMan.TryGetComponent <ApcPowerReceiverComponent>(Owner, out var powerReceiverComponent) || !powerReceiverComponent.Powered) { return(false); } if (_entMan.TryGetComponent(eventArgs.Using, out ProduceComponent? produce) && produce.Seed != null) { eventArgs.User.PopupMessageCursor(Loc.GetString("seed-extractor-component-interact-message", ("name", _entMan.GetComponent <MetaDataComponent>(eventArgs.Using).EntityName))); _entMan.QueueDeleteEntity(eventArgs.Using); var random = _random.Next(_minSeeds, _maxSeeds); for (var i = 0; i < random; i++) { produce.Seed.SpawnSeedPacket(_entMan.GetComponent <TransformComponent>(Owner).Coordinates, _entMan); } return(true); } return(false); }
private string?GetRandomPrototype() { var defaultProto = _prototypes?.Keys.FirstOrDefault(); if (defaultProto == null) { return(null); } DebugTools.AssertNotNull(_prototypes); if (_prototypes !.Count == 1) { return(defaultProto); } var probResult = _random.Next(0, 100); var total = 0; foreach (var item in _prototypes) { total += item.Value; if (probResult < total) { return(item.Key); } } return(defaultProto); }
private void OnInteractUsing(EntityUid uid, SeedExtractorComponent component, InteractUsingEvent args) { if (!TryComp <ApcPowerReceiverComponent>(uid, out var powerReceiverComponent) || !powerReceiverComponent.Powered) { return; } if (TryComp(args.Used, out ProduceComponent? produce)) { if (!_prototypeManager.TryIndex <SeedPrototype>(produce.SeedName, out var seed)) { return; } _popupSystem.PopupCursor(Loc.GetString("seed-extractor-component-interact-message", ("name", args.Used)), Filter.Entities(args.User)); QueueDel(args.Used); var random = _random.Next(component.MinSeeds, component.MaxSeeds); var coords = Transform(uid).Coordinates; for (var i = 0; i < random; i++) { _botanySystem.SpawnSeedPacket(seed, coords); } } }
public override void Startup() { base.Startup(); EntitySystem.Get <AudioSystem>().PlayGlobal("/Audio/Announcements/radiation.ogg"); IoCManager.InjectDependencies(this); _timeElapsed = 0.0f; _pulsesRemaining = _robustRandom.Next(30, 100); var componentManager = IoCManager.Resolve <IComponentManager>(); foreach (var overlay in componentManager.EntityQuery <ServerOverlayEffectsComponent>()) { overlay.AddOverlay(SharedOverlayID.RadiationPulseOverlay); } }
public void Play(ScheduledSound schedule) { if (!schedule.Play) { return; } Timer.Spawn((int)schedule.Delay + (_random.Next((int)schedule.RandomDelay)), () => { if (!schedule.Play) { return; // We make sure this hasn't changed. } if (_audioSystem == null) { _audioSystem = IoCManager.Resolve <IEntitySystemManager>().GetEntitySystem <AudioSystem>(); } _audioSystem.Play(schedule.Filename, Owner, schedule.AudioParams); if (schedule.Times == 0) { _schedules.Remove(schedule); return; } if (schedule.Times > 0) { schedule.Times--; } Play(schedule); }); }
protected override void CycleChamberedBullet(int chamber) { DebugTools.Assert(chamber == 0); // Eject chambered bullet. var entity = RemoveFromChamber(chamber); entity.Transform.GridPosition = Owner.Transform.GridPosition; entity.Transform.LocalRotation = _bulletDropRandom.Pick(_randomBulletDirs).ToAngle(); var effect = $"/Audio/Guns/Casings/casingfall{_bulletDropRandom.Next(1, 4)}.ogg"; Owner.GetComponent <SoundComponent>().Play(effect, AudioParams.Default.WithVolume(-3)); if (Magazine != null) { var magComponent = Magazine.GetComponent <BallisticMagazineComponent>(); var bullet = magComponent.TakeBullet(); if (bullet != null) { LoadIntoChamber(0, bullet); } if (magComponent.CountLoaded == 0 && _autoEjectMagazine) { EjectMagazine(); if (_autoEjectSound != null) { Owner.GetComponent <SoundComponent>().Play(_autoEjectSound, AudioParams.Default.WithVolume(-5)); } } } _updateAppearance(); }
private void OnInteractUsing(EntityUid uid, SeedExtractorComponent component, InteractUsingEvent args) { if (!this.IsPowered(uid, EntityManager)) { return; } if (!TryComp(args.Used, out ProduceComponent? produce)) { return; } if (!_botanySystem.TryGetSeed(produce, out var seed)) { return; } _popupSystem.PopupCursor(Loc.GetString("seed-extractor-component-interact-message", ("name", args.Used)), Filter.Entities(args.User), PopupType.Medium); QueueDel(args.Used); var random = _random.Next(component.MinSeeds, component.MaxSeeds); var coords = Transform(uid).Coordinates; if (random > 1) { seed.Unique = false; } for (var i = 0; i < random; i++) { _botanySystem.SpawnSeedPacket(seed, coords); } }
public static float NextFloat(this IRobustRandom random) { // This is pretty much the CoreFX implementation. // So credits to that. // Except using float instead of double. return(random.Next() * 4.6566128752458E-10f); }
/// <summary> /// Russian Roulette /// </summary> public void Spin() { var random = _random.Next(_ammoSlots.Length - 1); _currentSlot = random; SoundSystem.Play(Filter.Pvs(Owner), _soundSpin.GetSound(), Owner, AudioParams.Default.WithVolume(-2)); Dirty(); }
public static T PickAndTake <T>(this IRobustRandom random, IList <T> list) { var index = random.Next(list.Count); var element = list[index]; list.RemoveAt(index); return(element); }
/// <summary> /// Finds 2-5 random, alive entities that can host diseases /// and gives them a randomly selected disease. /// They all get the same disease. /// </summary> public override void Startup() { base.Startup(); HashSet <EntityUid> stationsToNotify = new(); List <DiseaseCarrierComponent> aliveList = new(); foreach (var(carrier, mobState) in _entityManager.EntityQuery <DiseaseCarrierComponent, MobStateComponent>()) { if (!mobState.IsDead()) { aliveList.Add(carrier); } } _random.Shuffle(aliveList); /// We're going to filter the above out to only alive mobs. Might change after future mobstate rework var toInfect = _random.Next(2, 5); var diseaseName = _random.Pick(NotTooSeriousDiseases); if (!_prototypeManager.TryIndex(diseaseName, out DiseasePrototype? disease)) { return; } var diseaseSystem = EntitySystem.Get <DiseaseSystem>(); var entSysMgr = IoCManager.Resolve <IEntitySystemManager>(); var stationSystem = entSysMgr.GetEntitySystem <StationSystem>(); var chatSystem = entSysMgr.GetEntitySystem <ChatSystem>(); // Now we give it to people in the list of living disease carriers earlier foreach (var target in aliveList) { if (toInfect-- == 0) { break; } diseaseSystem.TryAddDisease(target.Owner, disease, target); var station = stationSystem.GetOwningStation(target.Owner); if (station == null) { continue; } stationsToNotify.Add((EntityUid)station); } if (!AnnounceEvent) { return; } foreach (var station in stationsToNotify) { chatSystem.DispatchStationAnnouncement(station, Loc.GetString("station-event-disease-outbreak-announcement"), playDefaultSound: false, colorOverride: Color.YellowGreen); } }
private void MoveSingulo(SingularityComponent singularity, PhysicsComponent physics) { if (singularity.Level <= 1) { return; } // TODO: Could try gradual changes instead but for now just try to replicate var pushVector = new Vector2(_robustRandom.Next(-10, 10), _robustRandom.Next(-10, 10)); if (pushVector == Vector2.Zero) { return; } physics.LinearVelocity = Vector2.Zero; physics.LinearVelocity = pushVector.Normalized * 2; }
public void ExecutePlayerAction(PlayerAction action) { if (!_running) { return; } switch (action) { case PlayerAction.Attack: var attackAmount = _random.Next(2, 6); _latestPlayerActionMessage = $"You attack {_enemyName} for {attackAmount}!"; EntitySystem.Get <AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/player_attack.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f)); if (!Owner._enemyInvincibilityFlag) { _enemyHp -= attackAmount; } _turtleTracker -= _turtleTracker > 0 ? 1 : 0; break; case PlayerAction.Heal: var pointAmount = _random.Next(1, 3); var healAmount = _random.Next(6, 8); _latestPlayerActionMessage = $"You use {pointAmount} magic to heal for {healAmount} damage!"; EntitySystem.Get <AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/player_heal.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f)); if (!Owner._playerInvincibilityFlag) { _playerMp -= pointAmount; } _playerHp += healAmount; _turtleTracker++; break; case PlayerAction.Recharge: var charge_amount = _random.Next(4, 7); _latestPlayerActionMessage = $"You regain {charge_amount} points"; EntitySystem.Get <AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/player_charge.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f)); _playerMp += charge_amount; _turtleTracker -= _turtleTracker > 0 ? 1 : 0; break; } if (!CheckGameConditions()) { _running = false; return; } ValidateVars(); ExecuteAiAction(); if (!CheckGameConditions()) { _running = false; return; } ValidateVars(); UpdateUi(); }
public override void Startup() { base.Startup(); var stationSystem = EntitySystem.Get <StationSystem>(); var stationJobsSystem = EntitySystem.Get <StationJobsSystem>(); if (stationSystem.Stations.Count == 0) { return; // No stations } var chosenStation = _random.Pick(stationSystem.Stations.ToList()); var jobList = stationJobsSystem.GetJobs(chosenStation).Keys.ToList(); // Low chance to completely change up the late-join landscape by closing all positions except infinite slots. // Lower chance than the /tg/ equivalent of this event. if (_random.Prob(0.25f)) { var chosenJob = _random.PickAndTake(jobList); stationJobsSystem.MakeJobUnlimited(chosenStation, chosenJob); // INFINITE chaos. foreach (var job in jobList) { if (stationJobsSystem.IsJobUnlimited(chosenStation, job)) { continue; } stationJobsSystem.TrySetJobSlot(chosenStation, job, 0); } } else { // Changing every role is maybe a bit too chaotic so instead change 20-30% of them. for (var i = 0; i < _random.Next((int)(jobList.Count * 0.20), (int)(jobList.Count * 0.30)); i++) { var chosenJob = _random.PickAndTake(jobList); if (stationJobsSystem.IsJobUnlimited(chosenStation, chosenJob)) { continue; } stationJobsSystem.TryAdjustJobSlot(chosenStation, chosenJob, _random.Next(-3, 6)); } } }
public override void Startup() { base.Startup(); var targetList = _entityManager.EntityQuery <SentienceTargetComponent>().ToList(); _random.Shuffle(targetList); var toMakeSentient = _random.Next(2, 5); var groups = new HashSet <string>(); foreach (var target in targetList) { if (toMakeSentient-- == 0) { break; } MakeSentientCommand.MakeSentient(target.Owner, _entityManager); _entityManager.RemoveComponent <SentienceTargetComponent>(target.Owner); var comp = _entityManager.AddComponent <GhostTakeoverAvailableComponent>(target.Owner); comp.RoleName = _entityManager.GetComponent <MetaDataComponent>(target.Owner).EntityName; comp.RoleDescription = Loc.GetString("station-event-random-sentience-role-description", ("name", comp.RoleName)); groups.Add(target.FlavorKind); } if (groups.Count == 0) { return; } var groupList = groups.ToList(); var kind1 = groupList.Count > 0 ? groupList[0] : "???"; var kind2 = groupList.Count > 1 ? groupList[1] : "???"; var kind3 = groupList.Count > 2 ? groupList[2] : "???"; _chatManager.DispatchStationAnnouncement( Loc.GetString("station-event-random-sentience-announcement", ("kind1", kind1), ("kind2", kind2), ("kind3", kind3), ("amount", groupList.Count), ("data", Loc.GetString($"random-sentience-event-data-{_random.Next(1, 6)}")), ("strength", Loc.GetString($"random-sentience-event-strength-{_random.Next(1, 8)}"))) ); }
private void MoveSingulo(ServerSingularityComponent singularity, PhysicsComponent physics) { // To prevent getting stuck, ServerSingularityComponent will zero the velocity of a singularity when it goes to a level <= 1 (see here). if (singularity.Level <= 1) { return; } // TODO: Could try gradual changes instead but for now just try to replicate var pushVector = new Vector2(_robustRandom.Next(-10, 10), _robustRandom.Next(-10, 10)); if (pushVector == Vector2.Zero) { return; } physics.LinearVelocity = Vector2.Zero; physics.LinearVelocity = pushVector.Normalized * 2; }
private void SetupKudzu(EntityUid uid, GrowingKudzuComponent component, ComponentAdd args) { if (!EntityManager.TryGetComponent <AppearanceComponent>(uid, out var appearance)) { return; } appearance.SetData(KudzuVisuals.Variant, _robustRandom.Next(1, 3)); appearance.SetData(KudzuVisuals.GrowthLevel, 1); }
private void OnComponentStartup(EntityUid uid, ThirstComponent component, ComponentStartup args) { component.CurrentThirst = _random.Next( (int)component.ThirstThresholds[ThirstThreshold.Thirsty] + 10, (int)component.ThirstThresholds[ThirstThreshold.Okay] - 1); component.CurrentThirstThreshold = GetThirstThreshold(component, component.CurrentThirst); component.LastThirstThreshold = ThirstThreshold.Okay; // TODO: Potentially change this -> Used Okay because no effects. // TODO: Check all thresholds make sense and throw if they don't. UpdateEffects(component); }
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 ExecutePlayerAction(PlayerAction action) { if (!_running) { return; } switch (action) { case PlayerAction.Attack: var attackAmount = _random.Next(2, 6); _latestPlayerActionMessage = Loc.GetString("You attack {0} for {1}!", _enemyName, attackAmount); SoundSystem.Play(Filter.Pvs(_owner.Owner), "/Audio/Effects/Arcade/player_attack.ogg", _owner.Owner, AudioParams.Default.WithVolume(-4f)); if (!_owner._enemyInvincibilityFlag) { _enemyHp -= attackAmount; } _turtleTracker -= _turtleTracker > 0 ? 1 : 0; break; case PlayerAction.Heal: var pointAmount = _random.Next(1, 3); var healAmount = _random.Next(6, 8); _latestPlayerActionMessage = Loc.GetString("You use {0} magic to heal for {1} damage!", pointAmount, healAmount); SoundSystem.Play(Filter.Pvs(_owner.Owner), "/Audio/Effects/Arcade/player_heal.ogg", _owner.Owner, AudioParams.Default.WithVolume(-4f)); if (!_owner._playerInvincibilityFlag) { _playerMp -= pointAmount; } _playerHp += healAmount; _turtleTracker++; break; case PlayerAction.Recharge: var chargeAmount = _random.Next(4, 7); _latestPlayerActionMessage = Loc.GetString("You regain {0} points", chargeAmount); SoundSystem.Play(Filter.Pvs(_owner.Owner), "/Audio/Effects/Arcade/player_charge.ogg", _owner.Owner, AudioParams.Default.WithVolume(-4f)); _playerMp += chargeAmount; _turtleTracker -= _turtleTracker > 0 ? 1 : 0; break; } if (!CheckGameConditions()) { return; } ValidateVars(); ExecuteAiAction(); if (!CheckGameConditions()) { return; } ValidateVars(); UpdateUi(); }
protected override void Startup() { base.Startup(); // Similar functionality to SS13. Should also stagger people going to the chef. _currentHunger = _random.Next( (int)_hungerThresholds[HungerThreshold.Peckish] + 10, (int)_hungerThresholds[HungerThreshold.Okay] - 1); _currentHungerThreshold = GetHungerThreshold(_currentHunger); _lastHungerThreshold = HungerThreshold.Okay; // TODO: Potentially change this -> Used Okay because no effects. HungerThresholdEffect(true); }
private string Accentuate(string message, float scale) { var sb = new StringBuilder(); // This is pretty much ported from TG. foreach (var character in message) { if (_random.Prob(scale / 3f)) { var lower = char.ToLowerInvariant(character); var newString = lower switch { 'o' => "u", 's' => "ch", 'a' => "ah", 'u' => "oo", 'c' => "k", _ => $"{character}", }; sb.Append(newString); } if (_random.Prob(scale / 20f)) { if (character == ' ') { sb.Append(Loc.GetString("slur-accent-confused")); } else if (character == '.') { sb.Append(' '); sb.Append(Loc.GetString("slur-accent-burp")); } } if (!_random.Prob(scale * 3 / 20)) { sb.Append(character); continue; } var next = _random.Next(1, 3) switch { 1 => "'", 2 => $"{character}{character}", _ => $"{character}{character}{character}", }; sb.Append(next); } return(sb.ToString()); }
public override void Startup() { base.Startup(); // Essentially we'll pick out a target amount of gas to leak, then a rate to leak it at, then work out the duration from there. if (TryFindRandomTile(out _targetTile, out _targetStation, out _targetGrid, out _targetCoords)) { _foundTile = true; _leakGas = _robustRandom.Pick(LeakableGases); // Was 50-50 on using normal distribution. var totalGas = (float)_robustRandom.Next(MinimumGas, MaximumGas); _molesPerSecond = _robustRandom.Next(MinimumMolesPerSecond, MaximumMolesPerSecond); EndAfter = totalGas / _molesPerSecond + StartAfter; Logger.InfoS("stationevents", $"Leaking {totalGas} of {_leakGas} over {EndAfter - StartAfter} seconds at {_targetTile}"); } // Look technically if you wanted to guarantee a leak you'd do this in announcement but having the announcement // there just to f**k with people even if there is no valid tile is funny. }
protected override void Startup() { base.Startup(); _currentThirst = _random.Next( (int)_thirstThresholds[ThirstThreshold.Thirsty] + 10, (int)_thirstThresholds[ThirstThreshold.Okay] - 1); _currentThirstThreshold = GetThirstThreshold(_currentThirst); _lastThirstThreshold = ThirstThreshold.Okay; // TODO: Potentially change this -> Used Okay because no effects. // TODO: Check all thresholds make sense and throw if they don't. ThirstThresholdEffect(true); }