Fix "ыыыы" (#3516)

This commit is contained in:
iertis 2025-12-26 19:44:36 +05:00 committed by GitHub
parent 8b898c2a36
commit a700c7628e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
188 changed files with 2169 additions and 1234 deletions

View file

@ -373,7 +373,7 @@ public sealed partial class AdminLogsControl : Control
for (var i = 0; i < impacts.Length - 1; i++)
{
LogImpactContainer.GetChild(i).StyleClasses.Add("ButtonSquare");
LogImpactContainer.GetChild(i).StyleClasses.Add(StyleClass.ButtonSquare);
}
LogImpactContainer.GetChild(LogImpactContainer.ChildCount - 1).StyleClasses.Add("OpenLeft");

View file

@ -5,7 +5,6 @@ using Content.Shared.IdentityManagement;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
namespace Content.Client.Botany.PlantAnalyzer;
@ -14,8 +13,8 @@ namespace Content.Client.Botany.PlantAnalyzer;
public sealed partial class PlantAnalyzerWindow : FancyWindow
{
private readonly IEntityManager _entityManager;
private readonly IPrototypeManager _prototypeManager;
private readonly IGameTiming _gameTiming;
private readonly PlantAnalyzerLocalizationHelper _localizationHelper;
public PlantAnalyzerWindow()
{
@ -23,8 +22,8 @@ public sealed partial class PlantAnalyzerWindow : FancyWindow
var dependencies = IoCManager.Instance!;
_entityManager = dependencies.Resolve<IEntityManager>();
_prototypeManager = dependencies.Resolve<IPrototypeManager>();
_gameTiming = dependencies.Resolve<IGameTiming>();
_localizationHelper = _entityManager.System<PlantAnalyzerLocalizationHelper>();
}
public void Populate(PlantAnalyzerScannedUserMessage msg)
@ -136,7 +135,7 @@ public sealed partial class PlantAnalyzerWindow : FancyWindow
{
var count = msg.TrayData.Chemicals.Count;
var holder = ContainerLabel.Text;
var chemicals = PlantAnalyzerLocalizationHelper.ChemicalsToLocalizedStrings(msg.TrayData.Chemicals, _prototypeManager);
var chemicals = _localizationHelper.ChemicalsToLocalizedStrings(msg.TrayData.Chemicals);
if (count == 0)
ChemicalsInWaterLabel.Text = Loc.GetString("plant-analyzer-soil-empty", ("holder", holder));
else
@ -155,7 +154,7 @@ public sealed partial class PlantAnalyzerWindow : FancyWindow
{
(string, string)[] parameters = [
("seedName", SeedLabel.Text),
("gases", PlantAnalyzerLocalizationHelper.GasesToLocalizedStrings(msg.TolerancesData.ConsumeGasses, _prototypeManager)),
("gases", _localizationHelper.GasesToLocalizedStrings(msg.TolerancesData.ConsumeGasses)),
("kpa", msg.TolerancesData.IdealPressure.ToString("0.00")),
("kpaTolerance", msg.TolerancesData.PressureTolerance.ToString("0.00")),
("temp", msg.TolerancesData.IdealHeat.ToString("0.00")),
@ -180,9 +179,9 @@ public sealed partial class PlantAnalyzerWindow : FancyWindow
// Section 5: Output
if (msg.ProduceData is not null)
{
var gases = PlantAnalyzerLocalizationHelper.GasesToLocalizedStrings(msg.ProduceData.ExudeGasses, _prototypeManager);
var (produce, producePlural) = PlantAnalyzerLocalizationHelper.ProduceToLocalizedStrings(msg.ProduceData.Produce, _prototypeManager);
var chemicals = PlantAnalyzerLocalizationHelper.ChemicalsToLocalizedStrings(msg.ProduceData.Chemicals, _prototypeManager);
var gases = _localizationHelper.GasesToLocalizedStrings(msg.ProduceData.ExudeGasses);
var (produce, producePlural, firstProduce) = _localizationHelper.ProduceToLocalizedStrings(msg.ProduceData.Produce);
var chemicals = _localizationHelper.ChemicalsToLocalizedStrings(msg.ProduceData.Chemicals);
(string, object)[] parameters = [
("yield", msg.ProduceData.Yield),
@ -190,7 +189,7 @@ public sealed partial class PlantAnalyzerWindow : FancyWindow
("gases", gases),
("potency", Loc.GetString(msg.ProduceData.Potency)),
("seedless", msg.ProduceData.Seedless),
("firstProduce", msg.ProduceData.Produce.FirstOrDefault().Id ?? ""),
("firstProduce", firstProduce),
("produce", produce),
("producePlural", producePlural),
("chemCount", msg.ProduceData.Chemicals.Count),

View file

@ -55,7 +55,7 @@ namespace Content.Client.Info
var roadmapButton = new Button
{
Text = Loc.GetString("server-info-roadmap-button"),
StyleClasses = { StyleBase.ButtonCaution },
StyleClasses = { StyleClass.ButtonSquare },
};
roadmapButton.OnPressed += _ => UserInterfaceManager.GetUIController<RoadmapUIController>().ToggleRoadmap();
buttons.AddChild(roadmapButton);

View file

@ -22,18 +22,15 @@ using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Content.Client.Changelog;
using Content.Client.Parallax.Managers;
using Content.Server.GameTicking.Prototypes;
using Content.Shared._Sunrise.Lobby;
using Content.Shared._Sunrise.ServersHub;
using Content.Shared._Sunrise.SunriseCCVars;
using Content.Shared.GameTicking;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Markdown;
using Robust.Shared.Serialization.Markdown.Mapping;
using Serilog;
using Content.Shared.GameTicking.Prototypes;
namespace Content.Client.Lobby
{
@ -55,7 +52,6 @@ namespace Content.Client.Lobby
[Dependency] private readonly ContributorsManager _contributorsManager = default!;
[Dependency] private readonly ChangelogManager _changelogManager = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private ClientGameTicker _gameTicker = default!;
private ContentAudioSystem _contentAudioSystem = default!;
@ -406,7 +402,7 @@ namespace Content.Client.Lobby
private void SetLobbyAnimation(string lobbyAnimation)
{
if (!_prototypeManager.TryIndex<LobbyAnimationPrototype>(lobbyAnimation, out var lobbyAnimationPrototype))
if (!_protoMan.TryIndex<LobbyAnimationPrototype>(lobbyAnimation, out var lobbyAnimationPrototype))
return;
if (Lobby == null)
@ -421,7 +417,7 @@ namespace Content.Client.Lobby
private void SetLobbyArt(string lobbyArt)
{
if (!_prototypeManager.TryIndex<LobbyBackgroundPrototype>(lobbyArt, out var lobbyArtPrototype))
if (!_protoMan.TryIndex<LobbyBackgroundPrototype>(lobbyArt, out var lobbyArtPrototype))
return;
if (Lobby == null)
@ -435,7 +431,7 @@ namespace Content.Client.Lobby
private void SetLobbyParallax(string lobbyParallax)
{
if (!_prototypeManager.TryIndex<LobbyParallaxPrototype>(lobbyParallax, out var lobbyParallaxPrototype))
if (!_protoMan.TryIndex<LobbyParallaxPrototype>(lobbyParallax, out var lobbyParallaxPrototype))
return;
if (Lobby == null)

View file

@ -115,7 +115,7 @@ public sealed partial class RequirementsSelector : BoxContainer
Text = Loc.GetString("role-timer-locked"),
Visible = true,
HorizontalAlignment = HAlignment.Center,
StyleClasses = {StyleBase.StyleClassLabelSubText},
StyleClasses = { "StyleClassLabelSubText" },
};
_lockStripe.Children.Clear();
@ -136,7 +136,7 @@ public sealed partial class RequirementsSelector : BoxContainer
Visible = true,
HorizontalAlignment = HAlignment.Center,
FontColorOverride = Color.Red,
StyleClasses = {StyleBase.StyleClassLabelSubText},
StyleClasses = { "StyleClassLabelSubText" },
};
_lockStripe.Children.Clear();

View file

@ -1,8 +1,8 @@
using Content.Client.Audio;
using Content.Server.GameTicking.Prototypes;
using Content.Shared._Sunrise.Lobby;
using Content.Shared._Sunrise.SunriseCCVars;
using Content.Shared.GameTicking;
using Content.Shared.GameTicking.Prototypes;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.XAML;

View file

@ -1,6 +1,5 @@
using System.Linq;
using Content.Client.UserInterface.Screens;
using Content.Server.GameTicking.Prototypes;
using Content.Shared._Sunrise.Lobby;
using Content.Shared._Sunrise.SunriseCCVars;
using Content.Shared.CCVar;

View file

@ -32,6 +32,9 @@ using Robust.Shared.Utility;
using SharedGunSystem = Content.Shared.Weapons.Ranged.Systems.SharedGunSystem;
using TimedDespawnComponent = Robust.Shared.Spawners.TimedDespawnComponent;
using Robust.Shared.Configuration;
using Content.Shared.Damage;
using Robust.Shared.Audio;
using Content.Shared.Weapons.Hitscan.Events;
namespace Content.Client.Weapons.Ranged.Systems;
@ -125,40 +128,37 @@ public sealed partial class GunSystem : SharedGunSystem
private void OnHitscan(HitscanEvent ev)
{
var hitscan = _proto.Index(ev.Hitscan);
//The real bullet speed is so high that the bullet isnt visible at all. So, let's slow it down 5x.
var bulletSpeed = hitscan.Speed / 5000;
foreach (var effects in ev.Effects)
foreach (var trace in ev.Traces)
{
var delay = 0f;
foreach (var effect in effects)
delay = FireEffect(hitscan, bulletSpeed, delay, effect);
delay = FireEffect(ev, delay, trace);
}
}
private float FireEffect(HitscanPrototype hitscan, float bulletSpeed, float delay, Effect effect)
private float FireEffect(HitscanEvent visuals, float delay, HitscanTrace trace)
{
var length = effect.Distance / bulletSpeed;
if (effect.MuzzleCoordinates is { } muzzleCoordinates)
//The real bullet speed is so high that the bullet isnt visible at all. So, let's slow it down 5x.
var length = trace.Distance / (visuals.Speed / 5000);
if (trace.MuzzleCoordinates is { } muzzleCoordinates)
{
if (hitscan.MuzzleFlash is { } mozzle && (_tracesEnabled || hitscan.Bullet is null))
RenderFlash(muzzleCoordinates, effect.Angle, mozzle, 1f, false, false, length, delay);
if (visuals.MuzzleFlash is { } mozzle && (_tracesEnabled || visuals.Bullet is null))
RenderFlash(muzzleCoordinates, trace.Angle, mozzle, 1f, false, false, length, delay);
if (hitscan.Bullet is { } bullet)
RenderBullet(muzzleCoordinates, effect.Angle, bullet, effect.Distance - 1.5f, length, delay);
if (visuals.Bullet is { } bullet)
RenderBullet(muzzleCoordinates, trace.Angle, bullet, trace.Distance - 1.5f, length, delay);
}
if (hitscan.TravelFlash is { } travel && effect.TravelCoordinates is { } travelCoordinates && (_tracesEnabled || hitscan.Bullet is null))
RenderFlash(travelCoordinates, effect.Angle, travel, effect.Distance - 1.5f, true, false, length, delay);
if (visuals.TravelFlash is { } travel && trace.TravelCoordinates is { } travelCoordinates && (_tracesEnabled || visuals.Bullet is null))
RenderFlash(travelCoordinates, trace.Angle, travel, trace.Distance - 1.5f, true, false, length, delay);
delay += length;
if ((hitscan.ImpactFlash is not null || effect.ImpactEnt is not null) && (_tracesEnabled || hitscan.Bullet is null))
if ((visuals.ImpactFlash is not null || trace.ImpactedEnt is not null) && (_tracesEnabled || visuals.Bullet is null))
Timer.Spawn((int)delay, () =>
{
if (hitscan.ImpactFlash is { } impact)
RenderFlash(effect.ImpactCoordinates, effect.Angle, impact, 1f, false, true, length, delay);
if (visuals.ImpactFlash is { } impact)
RenderFlash(trace.ImpactCoordinates, trace.Angle, impact, 1f, false, true, length, delay);
if (effect.ImpactEnt is { } netEnt && GetEntity(netEnt) is EntityUid ent)
RenderDisplacementImpact(GetCoordinates(effect.ImpactCoordinates), effect.Angle, ent);
if (trace.ImpactedEnt is { } netEnt && GetEntity(netEnt) is EntityUid ent)
RenderDisplacementImpact(GetCoordinates(trace.ImpactCoordinates), trace.Angle, ent);
});
return delay;
}
@ -640,4 +640,6 @@ public sealed partial class GunSystem : SharedGunSystem
_animPlayer.Stop(gunUid, uidPlayer, "muzzle-flash-light");
_animPlayer.Play((gunUid, uidPlayer), animTwo, "muzzle-flash-light");
}
public override void PlayImpactSound(EntityUid otherEntity, DamageSpecifier? modifiedDamage, SoundSpecifier? weaponSound, bool forceWeaponSound) {}
}

View file

@ -37,7 +37,7 @@ public partial class ListViewSelectorWindow : DefaultWindow
MinSize = new Vector2(100, 100),
MaxSize = new Vector2(100, 100),
HorizontalExpand = true,
StyleClasses = { StyleBase.ButtonSquare },
StyleClasses = { StyleClass.ButtonSquare },
ToggleMode = false,
ToolTip = Loc.GetString($"ent-{item}"),
TooltipDelay = 0.01f,

View file

@ -438,7 +438,7 @@ public sealed partial class CustomInteractionEditor : DefaultWindow
var removeButton = new Button
{
Text = "✕",
StyleClasses = { "ButtonSquare" },
StyleClasses = { StyleClass.ButtonSquare },
MinWidth = 22,
MinHeight = 22,
Label = { FontColorOverride = PrimaryColor}
@ -494,7 +494,7 @@ public sealed partial class CustomInteractionEditor : DefaultWindow
var removeButton = new Button
{
Text = "✕",
StyleClasses = { "ButtonSquare" },
StyleClasses = { StyleClass.ButtonSquare },
MinWidth = 22,
MinHeight = 22,
Label = { FontColorOverride = PrimaryColor}
@ -553,7 +553,7 @@ public sealed partial class CustomInteractionEditor : DefaultWindow
var closeButton = new Button
{
Text = "ОК",
StyleClasses = { "ButtonSquare" },
StyleClasses = { StyleClass.ButtonSquare },
HorizontalAlignment = HAlignment.Center,
MinWidth = 80,
MinHeight = 30

View file

@ -468,7 +468,7 @@ public sealed partial class InteractionsUIWindow : DefaultWindow
HorizontalExpand = true,
MinHeight = 40,
MaxHeight = 45,
StyleClasses = { "ButtonSquare" },
StyleClasses = { StyleClass.ButtonSquare },
Disabled = isOnCooldown
};
@ -535,7 +535,7 @@ public sealed partial class InteractionsUIWindow : DefaultWindow
{
MinSize = new Vector2(32, 45),
MaxSize = new Vector2(32, 45),
StyleClasses = { "ButtonSquare" },
StyleClasses = { StyleClass.ButtonSquare },
Margin = new Thickness(2, 0, 0, 0),
VerticalAlignment = VAlignment.Center
};
@ -610,7 +610,7 @@ public sealed partial class InteractionsUIWindow : DefaultWindow
HorizontalExpand = true,
MinHeight = 40,
MaxHeight = 45,
StyleClasses = { "ButtonSquare" },
StyleClasses = { StyleClass.ButtonSquare },
Disabled = isOnCooldown,
};
@ -678,7 +678,7 @@ public sealed partial class InteractionsUIWindow : DefaultWindow
{
MinSize = new Vector2(32, 44),
MaxSize = new Vector2(32, 44),
StyleClasses = { "ButtonSquare" },
StyleClasses = { StyleClass.ButtonSquare },
Margin = new Thickness(2, 0, 0, 0),
VerticalAlignment = VAlignment.Center
};
@ -967,7 +967,7 @@ public sealed partial class InteractionsUIWindow : DefaultWindow
var editButton = new Button
{
Text = "Редактировать",
StyleClasses = { "ButtonSquare" },
StyleClasses = { StyleClass.ButtonSquare },
Margin = new Thickness(0, 0, 4, 0)
};
@ -981,7 +981,7 @@ public sealed partial class InteractionsUIWindow : DefaultWindow
var deleteButton = new Button
{
Text = "Удалить",
StyleClasses = { "ButtonSquare" },
StyleClasses = { StyleClass.ButtonSquare },
};
deleteButton.StyleBoxOverride = new StyleBoxFlat
@ -1120,7 +1120,7 @@ public sealed partial class InteractionsUIWindow : DefaultWindow
var cancelButton = new Button
{
Text = "Отмена",
StyleClasses = { "ButtonSquare" },
StyleClasses = { StyleClass.ButtonSquare },
Margin = new Thickness(0, 0, 4, 0)
};
@ -1134,7 +1134,7 @@ public sealed partial class InteractionsUIWindow : DefaultWindow
var confirmButton = new Button
{
Text = "Удалить",
StyleClasses = { "ButtonSquare" },
StyleClasses = { StyleClass.ButtonSquare },
};
confirmButton.StyleBoxOverride = new StyleBoxFlat

View file

@ -439,12 +439,12 @@ public sealed class MentorHelpUIController : UIController, IOnSystemChanged<Ment
if (hasUnread)
{
GameMHelpButton?.StyleClasses.Add(MenuButton.StyleClassRedTopButton);
GameMHelpButton?.StyleClasses.Add("StyleClassRedTopButton");
LobbyMHelpButton?.StyleClasses.Add("ButtonColorRed");
}
else
{
GameMHelpButton?.StyleClasses.Remove(MenuButton.StyleClassRedTopButton);
GameMHelpButton?.StyleClasses.Remove("StyleClassRedTopButton");
LobbyMHelpButton?.StyleClasses.Remove("ButtonColorRed");
}

View file

@ -506,14 +506,14 @@ public sealed partial class SponsorTierEntry : Control
{
SetSize = new Vector2(200, 200),
Margin = new Thickness(5, 5, 5, 5),
StyleClasses = { StyleBase.ButtonSquare },
StyleClasses = { StyleClass.ButtonSquare },
};
var box = new BoxContainer()
{
Orientation = BoxContainer.LayoutOrientation.Vertical,
Margin = new Thickness(5, 5, 5, 5),
StyleClasses = { StyleBase.ButtonSquare },
StyleClasses = { StyleClass.ButtonSquare },
Align = BoxContainer.AlignMode.Center
};
@ -546,14 +546,14 @@ public sealed partial class SponsorTierEntry : Control
{
SetSize = new Vector2(200, 200),
Margin = new Thickness(5, 5, 5, 5),
StyleClasses = { StyleBase.ButtonSquare },
StyleClasses = { StyleClass.ButtonSquare },
};
var box = new BoxContainer()
{
Orientation = BoxContainer.LayoutOrientation.Vertical,
Margin = new Thickness(5, 5, 5, 5),
StyleClasses = { StyleBase.ButtonSquare },
StyleClasses = { StyleClass.ButtonSquare },
};
panel.AddChild(box);

View file

@ -155,7 +155,7 @@ public sealed partial class EmotesTabControl : BaseTabControl
return false;
if (!whitelistSystem.IsWhitelistPassOrNull(emote.Whitelist, player) ||
whitelistSystem.IsBlacklistPass(emote.Blacklist, player))
whitelistSystem.IsWhitelistFail(emote.Blacklist, player))
return false;
if (!emote.Available &&

View file

@ -156,7 +156,7 @@ public sealed partial class VerbsTabControl : BaseTabControl
return false;
if (!whitelistSystem.IsWhitelistPassOrNull(emote.Whitelist, player) ||
whitelistSystem.IsBlacklistPass(emote.Blacklist, player))
whitelistSystem.IsWhitelistFail(emote.Blacklist, player))
return false;
if (!emote.Available &&

View file

@ -149,7 +149,7 @@ public sealed class SuicideCommandTests
damageableComp = entManager.GetComponent<DamageableComponent>(player);
var slashProto = protoMan.Index(DamageType);
damageableSystem.TryChangeDamage(player, new DamageSpecifier(slashProto, FixedPoint2.New(46.5)), useModifier: false, useVariance: false); // Sunrise-Edit
damageableSystem.ChangeDamage(player, new DamageSpecifier(slashProto, FixedPoint2.New(46.5)), ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
});
// Check that running the suicide command kills the player

View file

@ -171,7 +171,7 @@ namespace Content.IntegrationTests.Tests.Damageable
var damageToDeal = FixedPoint2.New(types.Count * 5);
DamageSpecifier damage = new(group3, damageToDeal);
sDamageableSystem.TryChangeDamage(uid, damage, true, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(uid, damage, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
Assert.Multiple(() =>
{
@ -185,7 +185,7 @@ namespace Content.IntegrationTests.Tests.Damageable
});
// Heal
sDamageableSystem.TryChangeDamage(uid, -damage, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(uid, -damage, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
Assert.Multiple(() =>
{
@ -204,7 +204,7 @@ namespace Content.IntegrationTests.Tests.Damageable
Assert.That(types, Has.Count.EqualTo(3));
damage = new DamageSpecifier(group3, 14);
sDamageableSystem.TryChangeDamage(uid, damage, true, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(uid, damage, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
Assert.Multiple(() =>
{
@ -216,7 +216,7 @@ namespace Content.IntegrationTests.Tests.Damageable
});
// Heal
sDamageableSystem.TryChangeDamage(uid, -damage, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(uid, -damage, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
Assert.Multiple(() =>
{
@ -232,7 +232,7 @@ namespace Content.IntegrationTests.Tests.Damageable
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
});
damage = new DamageSpecifier(group1, FixedPoint2.New(10)) + new DamageSpecifier(type2b, FixedPoint2.New(10));
sDamageableSystem.TryChangeDamage(uid, damage, true, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(uid, damage, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
Assert.Multiple(() =>
{
@ -252,9 +252,9 @@ namespace Content.IntegrationTests.Tests.Damageable
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
// Test 'wasted' healing
sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(type3a, 5), useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(type3b, 7), useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(group3, -11), useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(uid, new DamageSpecifier(type3a, 5), ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(uid, new DamageSpecifier(type3b, 7), ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(uid, new DamageSpecifier(group3, -11), ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
Assert.Multiple(() =>
{
@ -264,11 +264,11 @@ namespace Content.IntegrationTests.Tests.Damageable
});
// Test Over-Healing
sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(group3, FixedPoint2.New(-100)), useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(uid, new DamageSpecifier(group3, FixedPoint2.New(-100)), ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
// Test that if no health change occurred, returns false
sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(group3, -100), useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(uid, new DamageSpecifier(group3, -100), ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
});
await pair.CleanReturnAsync();

View file

@ -45,7 +45,7 @@ namespace Content.IntegrationTests.Tests.Destructible
#pragma warning disable NUnit2045 // Interdependent assertions.
Assert.DoesNotThrow(() =>
{
sEntityManager.System<DamageableSystem>().TryChangeDamage(sDestructibleEntity, bruteDamage, true, useModifier: false, useVariance: false); // Sunrise-Edit
sEntityManager.System<DamageableSystem>().ChangeDamage(sDestructibleEntity, bruteDamage, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
});
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Has.Count.EqualTo(1));

View file

@ -65,12 +65,12 @@ namespace Content.IntegrationTests.Tests.Destructible
{
var bluntDamage = new DamageSpecifier(sPrototypeManager.Index<DamageTypePrototype>(TestBluntDamageTypeId), 10);
sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage, true, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(sDestructibleEntity, bluntDamage, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
// No thresholds reached yet, the earliest one is at 20 damage
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);
sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage, true, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(sDestructibleEntity, bluntDamage, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
// Only one threshold reached, 20
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Has.Count.EqualTo(1));
@ -89,7 +89,7 @@ namespace Content.IntegrationTests.Tests.Destructible
sTestThresholdListenerSystem.ThresholdsReached.Clear();
sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage * 3, true, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(sDestructibleEntity, bluntDamage * 3, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
// One threshold reached, 50, since 20 already triggered before and it has not been healed below that amount
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Has.Count.EqualTo(1));
@ -120,7 +120,7 @@ namespace Content.IntegrationTests.Tests.Destructible
sTestThresholdListenerSystem.ThresholdsReached.Clear();
// Damage for 50 again, up to 100 now
sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage * 5, true, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(sDestructibleEntity, bluntDamage * 5, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
// No thresholds reached as they weren't healed below the trigger amount
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);
@ -129,7 +129,7 @@ namespace Content.IntegrationTests.Tests.Destructible
sDamageableSystem.ClearAllDamage((sDestructibleEntity, sDamageableComponent));
// Damage for 100, up to 100
sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage * 10, true, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(sDestructibleEntity, bluntDamage * 10, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
// Two thresholds reached as damage increased past the previous, 20 and 50
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Has.Count.EqualTo(2));
@ -137,25 +137,25 @@ namespace Content.IntegrationTests.Tests.Destructible
sTestThresholdListenerSystem.ThresholdsReached.Clear();
// Heal the entity for 40 damage, down to 60
sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage * -4, true, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(sDestructibleEntity, bluntDamage * -4, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
// ThresholdsLookup don't work backwards
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);
// Damage for 10, up to 70
sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage, true, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(sDestructibleEntity, bluntDamage, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
// Not enough healing to de-trigger a threshold
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);
// Heal by 30, down to 40
sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage * -3, true, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(sDestructibleEntity, bluntDamage * -3, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
// ThresholdsLookup don't work backwards
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);
// Damage up to 50 again
sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage, true, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(sDestructibleEntity, bluntDamage, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
// The 50 threshold should have triggered again, after being healed
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Has.Count.EqualTo(1));
@ -190,7 +190,7 @@ namespace Content.IntegrationTests.Tests.Destructible
sDamageableSystem.ClearAllDamage((sDestructibleEntity, sDamageableComponent));
// Damage up to 50
sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage * 5, true, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(sDestructibleEntity, bluntDamage * 5, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
Assert.Multiple(() =>
{
@ -262,7 +262,7 @@ namespace Content.IntegrationTests.Tests.Destructible
}
// Damage the entity up to 50 damage again
sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage * 5, true, useModifier: false, useVariance: false); // Sunrise-Edit
sDamageableSystem.ChangeDamage(sDestructibleEntity, bluntDamage * 5, true, ignoreGlobalModifiers: true, useVariance: false); // Sunrise-Edit
Assert.Multiple(() =>
{

View file

@ -67,6 +67,7 @@ using Robust.Shared.Random;
using Robust.Shared.Spawners;
using Robust.Shared.Utility;
using Timer = Robust.Shared.Timing.Timer;
using Content.Shared.Damage;
namespace Content.Server.Administration.Systems;
@ -1198,7 +1199,7 @@ public sealed partial class AdminVerbSystem
{ "Radiation", GetDamageToKill(target) }
}
};
_damageable.SetDamage(target, Comp<DamageableComponent>(target), damageSpecifier);
_damageable.SetDamage(target, damageSpecifier);
}
private void Scorched(EntityUid target)
@ -1223,7 +1224,7 @@ public sealed partial class AdminVerbSystem
{ "Heat", GetDamageToKill(target) - 50 }
}
};
_damageable.SetDamage(target, Comp<DamageableComponent>(target), damageSpecifier);
_damageable.SetDamage(target, damageSpecifier);
});
}
}
@ -1251,7 +1252,7 @@ public sealed partial class AdminVerbSystem
{ "Toxin", GetDamageToKill(target) }
}
};
_damageable.SetDamage(target, Comp<DamageableComponent>(target), damageSpecifier);
_damageable.SetDamage(target, damageSpecifier);
}
private void BluespaceAway(EntityUid target)
@ -1287,6 +1288,6 @@ public sealed partial class AdminVerbSystem
}
};
_damageable.SetDamage(target, Comp<DamageableComponent>(target), damageSpecifier);
_damageable.SetDamage(target, damageSpecifier);
}
}

View file

@ -22,7 +22,8 @@ using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using Robust.Shared.Utility; //Sunrise-Edit
using Robust.Shared.Utility;
using Content.Shared.PowerCell.Components; //Sunrise-Edit
namespace Content.Server.Atmos.Monitor.Systems;
@ -37,7 +38,7 @@ public sealed class AtmosAlertsComputerSystem : SharedAtmosAlertsComputerSystem
[Dependency] private readonly NavMapSystem _navMapSystem = default!;
[Dependency] private readonly DeviceListSystem _deviceListSystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedPowerCellSystem _cell = default!;
[Dependency] private readonly PowerCellSystem _cell = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
private const float UpdateTime = 1.0f;
@ -207,7 +208,7 @@ public sealed class AtmosAlertsComputerSystem : SharedAtmosAlertsComputerSystem
// Sunrise-start
if (HasComp<ActivatableUIRequiresPowerCellComponent>(ent) && TryComp<PowerCellDrawComponent>(ent, out var draw))
{
if (_cell.HasActivatableCharge(ent, draw) || _cell.HasDrawCharge(ent, draw))
if (_cell.HasActivatableCharge(ent) || _cell.HasDrawCharge(ent))
{
Beep(ent, entConsole, highestAlert);
}

View file

@ -146,20 +146,22 @@ namespace Content.Server.Bible
var userEnt = Identity.Entity(args.User, EntityManager);
var targetEnt = Identity.Entity(args.Target.Value, EntityManager);
//Damage unholy creatures
// Sunrise-start
if (HasComp<UnholyComponent>(args.Target))
{
_damageableSystem.TryChangeDamage(args.Target.Value, component.DamageUnholy, true, origin: uid);
var othersMessage = Loc.GetString(component.LocPrefix + "-damage-unholy-others", ("user", Identity.Entity(args.User, EntityManager)), ("target", Identity.Entity(args.Target.Value, EntityManager)), ("bible", uid));
_popupSystem.PopupEntity(othersMessage, args.User, Filter.PvsExcept(args.User), true, PopupType.MediumCaution);
var othersUnholyMessage = Loc.GetString(component.LocPrefix + "-damage-unholy-others", ("user", Identity.Entity(args.User, EntityManager)), ("target", Identity.Entity(args.Target.Value, EntityManager)), ("bible", uid));
_popupSystem.PopupEntity(othersUnholyMessage, args.User, Filter.PvsExcept(args.User), true, PopupType.MediumCaution);
var selfMessage = Loc.GetString(component.LocPrefix + "-damage-unholy-self", ("target", Identity.Entity(args.Target.Value, EntityManager)), ("bible", uid));
_popupSystem.PopupEntity(selfMessage, args.User, args.User, PopupType.LargeCaution);
var selfUnholyMessage = Loc.GetString(component.LocPrefix + "-damage-unholy-self", ("target", Identity.Entity(args.Target.Value, EntityManager)), ("bible", uid));
_popupSystem.PopupEntity(selfUnholyMessage, args.User, args.User, PopupType.LargeCaution);
_delay.TryResetDelay((uid, useDelay));
return;
}
// Sunrise-end
// This only has a chance to fail if the target is not wearing anything on their head and is not a familiar..
if (!_invSystem.TryGetSlotEntity(args.Target.Value, "head", out _) && !HasComp<FamiliarComponent>(args.Target.Value))
@ -198,9 +200,9 @@ namespace Content.Server.Bible
_popupSystem.PopupEntity(othersMessage, args.User, Filter.PvsExcept(args.User), true, PopupType.Medium);
_popupSystem.PopupEntity(selfMessage, args.User, args.User, PopupType.Large);
}
RaiseLocalEvent(args.Target.Value, new MoodEffectEvent("GotBlessed")); // Sunrise Edit
RaiseLocalEvent(args.Target.Value, new MoodEffectEvent("GotBlessed")); // Sunrise Edit
}
private void AddSummonVerb(EntityUid uid, SummonableComponent component, GetVerbsEvent<AlternativeVerb> args)
{

View file

@ -1,15 +1,14 @@
using Content.Server.AbstractAnalyzer;
using Content.Server.Botany.Systems;
using Content.Shared.AbstractAnalyzer;
using Content.Shared.Paper;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Botany.Components;
namespace Content.Shared.Botany.Components;
/// <inheritdoc/>
[RegisterComponent, AutoGenerateComponentPause]
[Access(typeof(PlantAnalyzerSystem))]
[RegisterComponent, NetworkedComponent, AutoGenerateComponentPause]
public sealed partial class PlantAnalyzerComponent : AbstractAnalyzerComponent
{
/// <inheritdoc/>
@ -20,24 +19,25 @@ public sealed partial class PlantAnalyzerComponent : AbstractAnalyzerComponent
/// <summary>
/// When will the analyzer be ready to print again?
/// </summary>
[ViewVariables(VVAccess.ReadOnly)]
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
[AutoPausedField]
public TimeSpan PrintReadyAt = TimeSpan.Zero;
/// <summary>
/// How often can the analyzer print?
/// </summary>
[DataField("printCooldown")]
[DataField]
public TimeSpan PrintCooldown = TimeSpan.FromSeconds(5);
/// <summary>
/// The sound that's played when the analyzer prints off a report.
/// </summary>
[DataField("soundPrint")]
[DataField]
public SoundSpecifier SoundPrint = new SoundPathSpecifier("/Audio/Machines/short_print_and_rip.ogg");
/// <summary>
/// What the machine will print.
/// </summary>
[DataField("machineOutput", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string MachineOutput = "PlantAnalyzerReportPaper";
[DataField]
public EntProtoId<PaperComponent> MachineOutput = "PlantAnalyzerReportPaper";
}

View file

@ -149,7 +149,20 @@ public sealed partial class BotanySystem : EntitySystem
public IEnumerable<EntityUid> GenerateProduct(SeedData proto, EntityCoordinates position, int yieldMod = 1)
{
var totalYield = CalculateTotalYield(proto.Yield, yieldMod);
// Sunrise-start
// var totalYield = 0;
// if (proto.Yield > -1)
// {
// if (yieldMod < 0)
// totalYield = proto.Yield;
// else
// totalYield = proto.Yield * yieldMod;
// totalYield = Math.Max(1, totalYield);
// }
// Sunrise-end
var totalYield = CalculateTotalYield(proto.Yield, yieldMod); // Sunrise-edit, если тут появится конфликт, значит оффы мерджнули анализатор растений и надо все эдиты убрать
var products = new List<EntityUid>();
if (totalYield > 1 || proto.HarvestRepeat != HarvestType.NoRepeat)

View file

@ -1,11 +1,10 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using Content.Server.AbstractAnalyzer;
using Content.Server.Botany.Components;
using Content.Server.Popups;
using Content.Shared.AbstractAnalyzer;
using Content.Shared.Botany.Components;
using Content.Shared.Botany.PlantAnalyzer;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
using Content.Shared.Labels.EntitySystems;
@ -13,7 +12,6 @@ using Content.Shared.Paper;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
namespace Content.Server.Botany.Systems;
@ -27,9 +25,8 @@ public sealed class PlantAnalyzerSystem : AbstractAnalyzerSystem<PlantAnalyzerCo
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
[Dependency] private readonly PaperSystem _paperSystem = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly LabelSystem _labelSystem = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly PlantAnalyzerLocalizationHelper _localizationHelper = default!;
public override void Initialize()
{
@ -147,13 +144,13 @@ public sealed class PlantAnalyzerSystem : AbstractAnalyzerSystem<PlantAnalyzerCo
var seedName = data.PlantData is not null ? Loc.GetString(data.PlantData.SeedDisplayName) : null;
(string, object)[] parameters = [
("seedName", seedName ?? missingData),
("produce", data.ProduceData is not null ? PlantAnalyzerLocalizationHelper.ProduceToLocalizedStrings(data.ProduceData.Produce, _prototypeManager).Plural : missingData),
("produce", data.ProduceData is not null ? _localizationHelper.ProduceToLocalizedStrings(data.ProduceData.Produce).Plural : missingData),
("water", data.TolerancesData?.WaterConsumption.ToString("0.00") ?? missingData),
("nutrients", data.TolerancesData?.NutrientConsumption.ToString("0.00") ?? missingData),
("toxins", data.TolerancesData?.ToxinsTolerance.ToString("0.00") ?? missingData),
("pests", data.TolerancesData?.PestTolerance.ToString("0.00") ?? missingData),
("weeds", data.TolerancesData?.WeedTolerance.ToString("0.00") ?? missingData),
("gasesIn", data.TolerancesData is not null ? PlantAnalyzerLocalizationHelper.GasesToLocalizedStrings(data.TolerancesData.ConsumeGasses, _prototypeManager) : missingData),
("gasesIn", data.TolerancesData is not null ? _localizationHelper.GasesToLocalizedStrings(data.TolerancesData.ConsumeGasses) : missingData),
("kpa", data.TolerancesData?.IdealPressure.ToString("0.00") ?? missingData),
("kpaTolerance", data.TolerancesData?.PressureTolerance.ToString("0.00") ?? missingData),
("temp", data.TolerancesData?.IdealHeat.ToString("0.00") ?? missingData),
@ -162,15 +159,13 @@ public sealed class PlantAnalyzerSystem : AbstractAnalyzerSystem<PlantAnalyzerCo
("lightTolerance", data.TolerancesData?.LightTolerance.ToString("0.00") ?? missingData),
("yield", data.ProduceData?.Yield ?? -1),
("potency", data.ProduceData is not null ? Loc.GetString(data.ProduceData.Potency) : missingData),
("chemicals", data.ProduceData is not null ? PlantAnalyzerLocalizationHelper.ChemicalsToLocalizedStrings(data.ProduceData.Chemicals, _prototypeManager) : missingData),
("gasesOut", data.ProduceData is not null ? PlantAnalyzerLocalizationHelper.GasesToLocalizedStrings(data.ProduceData.ExudeGasses, _prototypeManager) : missingData),
("chemicals", data.ProduceData is not null ? _localizationHelper.ChemicalsToLocalizedStrings(data.ProduceData.Chemicals) : missingData),
("gasesOut", data.ProduceData is not null ? _localizationHelper.GasesToLocalizedStrings(data.ProduceData.ExudeGasses) : missingData),
("endurance", data.PlantData?.Endurance.ToString("0.00") ?? missingData),
("lifespan", data.PlantData?.Lifespan.ToString("0.00") ?? missingData),
("seeds", data.ProduceData is not null ? (data.ProduceData.Seedless ? "no" : "yes") : "other"),
("viable", data.PlantData is not null ? (data.PlantData.Viable ? "yes" : "no") : "other"),
("kudzu", data.PlantData is not null ? (data.PlantData.Kudzu ? "yes" : "no") : "other"),
("indent", " "),
("nl", "\n")
("kudzu", data.PlantData is not null ? (data.PlantData.Kudzu ? "yes" : "no") : "other")
];
_paperSystem.SetContent((printed, paperComp), Loc.GetString($"plant-analyzer-printout", [.. parameters]));

View file

@ -346,7 +346,7 @@ public sealed partial class ChatSystem : SharedChatSystem
bool playDefault = true,
SoundSpecifier? announcementSound = null,
bool playTts = true, // Sunrise-edit,
string? announceVoice = null,
string? announceVoice = null, // Sunrise-edit
Color? colorOverride = null
)
{
@ -430,11 +430,13 @@ public sealed partial class ChatSystem : SharedChatSystem
EntityUid source,
string message,
string? sender = null,
bool playDefault = true, // Sunrise-edit
bool playTts = true, // Sunrise-edit
Color? colorOverride = null,
string? announceVoice = null, // Sunrise-edit
SoundSpecifier? announcementSound = null)
bool playDefault = true, // Sunrise
bool playTts = true, // Sunrise
string? announceVoice = null, // Sunrise
bool playDefaultSound = true,
SoundSpecifier? announcementSound = null,
Color? colorOverride = null)
{
sender ??= Loc.GetString("chat-manager-sender-announcement");
@ -613,7 +615,7 @@ public sealed partial class ChatSystem : SharedChatSystem
SendInVoiceRange(ChatChannel.Local, message, wrappedMessage, source, range);
var ev = new EntitySpokeEvent(source, message, originalMessage, null, null);
var ev = new EntitySpokeEvent(source, message, null, null);
RaiseLocalEvent(source, ev, true);
// To avoid logging any messages sent by entities that are not players, like vendors, cloning, etc.
@ -708,7 +710,7 @@ public sealed partial class ChatSystem : SharedChatSystem
_replay.RecordServerMessage(new ChatMessage(ChatChannel.Whisper, message, wrappedMessage, GetNetEntity(source), null, MessageRangeHideChatForReplay(range)));
var ev = new EntitySpokeEvent(source, message, originalMessage, channel, obfuscatedMessage);
var ev = new EntitySpokeEvent(source, message, channel, obfuscatedMessage);
RaiseLocalEvent(source, ev, true);
if (!hideLog)
if (originalMessage == message)

View file

@ -1,6 +1,7 @@
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Hypospray.Events;
using Content.Shared.Chemistry.Events;
using Content.Shared.Clothing.EntitySystems;
namespace Content.Server.Chemistry.EntitySystems;
@ -15,17 +16,17 @@ public sealed class ServerHypospraySystem : EntitySystem
public override void Initialize()
{
base.Initialize();
// Subscribe to injection events after the shared system processes them
SubscribeLocalEvent<HyposprayComponent, HyposprayAfterInjectEvent>(OnAfterInject);
SubscribeLocalEvent<InjectorComponent, BeforeInjectTargetEvent>(OnAfterInject);
}
private void OnAfterInject(Entity<HyposprayComponent> entity, ref HyposprayAfterInjectEvent args)
private void OnAfterInject(Entity<InjectorComponent> entity, ref BeforeInjectTargetEvent args)
{
// Get the solution that was injected
if (_solutionContainers.TryGetSolution(entity.Owner, entity.Comp.SolutionName, out var hypoSpraySoln, out _))
{
_borgHypospray.TryAnnounceInjection(entity.Owner, args.User, args.Target, hypoSpraySoln.Value);
_borgHypospray.TryAnnounceInjection(entity.Owner, args.EntityUsingInjector, args.TargetGettingInjected, hypoSpraySoln.Value);
}
}
}
}

View file

@ -1,7 +1,6 @@
using Content.Server.DeviceLinking.Systems;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.PowerCell;
using Content.Shared._Sunrise.Biocode;
using Content.Shared.Actions;
using Content.Shared.Damage;
@ -20,6 +19,7 @@ using Content.Shared.Power.Components;
using Robust.Server.Containers;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Content.Shared.Damage.Systems;
namespace Content.Server.EnergyDome;
@ -183,13 +183,13 @@ public sealed partial class EnergyDomeSystem : EntitySystem
private void OnPowerCellChanged(Entity<EnergyDomeGeneratorComponent> generator, ref PowerCellChangedEvent args)
{
if (args.Ejected || !_powerCell.HasDrawCharge(generator))
if (args.Ejected || !_powerCell.HasDrawCharge(generator.Owner))
TurnOff(generator, true);
}
private void OnChargeChanged(Entity<EnergyDomeGeneratorComponent> generator, ref ChargeChangedEvent args)
{
if (args.Charge == 0)
if (args.CurrentCharge == 0)
TurnOff(generator, true);
}
private void OnDomeDamaged(Entity<EnergyDomeComponent> dome, ref DamageChangedEvent args)
@ -215,9 +215,9 @@ public sealed partial class EnergyDomeSystem : EntitySystem
_powerCell.TryGetBatteryFromSlot(generatorUid, out var cell);
if (cell != null)
{
_battery.UseCharge(cell.Owner, energyLeak);
_battery.UseCharge(cell.Value.Owner, energyLeak);
if (cell.CurrentCharge == 0)
if (cell.Value.Comp.ChargeRate == 0)
TurnOff((generatorUid, generatorComp), true);
}
}
@ -226,7 +226,7 @@ public sealed partial class EnergyDomeSystem : EntitySystem
if (TryComp<BatteryComponent>(generatorUid, out var battery)) {
_battery.UseCharge(generatorUid, energyLeak);
if (battery.CurrentCharge == 0)
if (battery.ChargeRate == 0)
TurnOff((generatorUid, generatorComp), true);
}
}
@ -265,9 +265,10 @@ public sealed partial class EnergyDomeSystem : EntitySystem
return false;
}
if (TryComp<PowerCellSlotComponent>(generator, out var powerCellSlot))
if (TryComp<PowerCellComponent>(generator, out var powerCellSlot))
{
if (!_powerCell.TryGetBatteryFromSlot(generator, out var cell) && !TryComp(generator, out cell))
if (!_powerCell.TryGetBatteryFromSlot(generator.Owner, out var cell) &&
!HasComp<BatteryComponent>(generator.Owner))
{
_audio.PlayPvs(generator.Comp.TurnOffSound, generator);
_popup.PopupEntity(
@ -276,7 +277,7 @@ public sealed partial class EnergyDomeSystem : EntitySystem
return false;
}
if (!_powerCell.HasDrawCharge(generator))
if (!_powerCell.HasDrawCharge(generator.Owner))
{
_audio.PlayPvs(generator.Comp.TurnOffSound, generator);
_popup.PopupEntity(
@ -288,7 +289,7 @@ public sealed partial class EnergyDomeSystem : EntitySystem
if (TryComp<BatteryComponent>(generator, out var battery))
{
if (battery.CurrentCharge == 0)
if (battery.ChargeRate == 0)
{
_audio.PlayPvs(generator.Comp.TurnOffSound, generator);
_popup.PopupEntity(
@ -334,10 +335,6 @@ public sealed partial class EnergyDomeSystem : EntitySystem
_powerCell.SetDrawEnabled(generator.Owner, true);
}
if (TryComp<BatterySelfRechargerComponent>(generator, out var recharger)) {
recharger.AutoRecharge = true;
}
generator.Comp.SpawnedDome = newDome;
_audio.PlayPvs(generator.Comp.TurnOnSound, generator);
generator.Comp.Enabled = true;
@ -377,10 +374,6 @@ public sealed partial class EnergyDomeSystem : EntitySystem
{
_powerCell.SetDrawEnabled(generator.Owner, false);
}
if (TryComp<BatterySelfRechargerComponent>(generator, out var recharger))
{
recharger.AutoRecharge = true;
}
_audio.PlayPvs(generator.Comp.TurnOffSound, generator);
if (startReloading)

View file

@ -2,6 +2,7 @@ using System.Linq;
using Content.Server.Administration;
using Content.Server.Maps;
using Content.Shared.Administration;
using Content.Shared.Maps;
using Robust.Shared.Console;
using Robust.Shared.Prototypes;

View file

@ -1,8 +1,8 @@
using Robust.Shared.Random;
using System.Linq;
using Content.Server.GameTicking.Prototypes;
using Content.Shared._Sunrise.Lobby;
using Content.Shared.GameTicking;
using Content.Shared.GameTicking.Prototypes;
namespace Content.Server.GameTicking;

View file

@ -636,7 +636,7 @@ namespace Content.Server.Ghost
DamageSpecifier damage = new(_prototypeManager.Index(AsphyxiationDamageType), dealtDamage);
_damageable.ChangeDamage(playerEntity.Value, damage, true, useVariance: false, useModifier: false); // Sunrise-Edit
_damageable.ChangeDamage(playerEntity.Value, damage, true, useVariance: false, ignoreGlobalModifiers: true); // Sunrise-Edit
}
}

View file

@ -1,9 +1,12 @@
using Content.Shared.Construction.Prototypes;
using Content.Shared.DeviceLinking;
using Content.Shared.Item;
using Content.Shared.Kitchen;
using Content.Shared.Kitchen.Components;
using Robust.Shared.Audio;
using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Kitchen.Components

View file

@ -35,13 +35,13 @@ public sealed class MechGunSystem : EntitySystem
|| !TryComp<MechComponent>(mechEquipment.EquipmentOwner.Value, out var mech))
return;
var chargeDelta = component.MaxCharge - component.CurrentCharge;
var chargeDelta = component.MaxCharge - component.ChargeRate;
// TODO: The battery charge of the mech would be spent directly when fired.
if (chargeDelta <= 0
|| mech.Energy - chargeDelta < 0
|| !_mech.TryChangeEnergy(mechEquipment.EquipmentOwner.Value, -chargeDelta, mech))
return;
_battery.SetCharge(uid, component.MaxCharge, component);
_battery.SetCharge(uid, component.MaxCharge);
}
}

View file

@ -37,6 +37,7 @@ using System.Linq;
using Content.Shared.Access.Components;
using Content.Shared.Access.Systems;
using Content.Shared.Chat;
using Content.Shared.Damage.Components;
namespace Content.Server.Mech.Systems;

View file

@ -1,4 +1,4 @@
using Content.Server.AbstractAnalyzer;
using Content.Shared.AbstractAnalyzer;
using Content.Shared.Damage.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
@ -10,11 +10,7 @@ namespace Content.Server.Medical.Components;
[Access(typeof(HealthAnalyzerSystem), typeof(CryoPodSystem))]
public sealed partial class HealthAnalyzerComponent : AbstractAnalyzerComponent
{
/// <inheritdoc/>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
[AutoPausedField]
public override TimeSpan NextUpdate { get; set; } = TimeSpan.Zero;
[DataField("damageContainers", customTypeSerializer: typeof(PrototypeIdListSerializer<DamageContainerPrototype>))]
public List<string>? DamageContainers;
}

View file

@ -16,6 +16,7 @@ using Robust.Server.GameObjects;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Map;
using Robust.Shared.Timing;
using Content.Shared.PowerCell.Components;
//Sunrise-Edit
@ -58,7 +59,7 @@ public sealed class CrewMonitoringConsoleSystem : EntitySystem
{
if (HasComp<ActivatableUIRequiresPowerCellComponent>(uid) && TryComp<PowerCellDrawComponent>(uid, out var draw))
{
if (_cell.HasActivatableCharge(uid, draw))
if (_cell.HasActivatableCharge(uid))
{
_audio.PlayPvs(component.CorpseAlertSound, uid);
}

View file

@ -260,7 +260,7 @@ public sealed class DefibrillatorSystem : EntitySystem
// Inject reagents if any are specified
if (component.Reagents.Count > 0 && TryComp<BloodstreamComponent>(target, out var bloodstream))
{
if (_solutionContainer.TryGetSolution(target, bloodstream.ChemicalSolutionName, out var solution))
if (_solutionContainer.TryGetSolution(target, bloodstream.BloodReferenceSolution.Name, out var solution))
{
foreach (var (reagent, amount) in component.Reagents)
_solutionContainer.TryAddReagent(solution.Value, reagent, FixedPoint2.New(amount), out _);

View file

@ -1,7 +1,5 @@
using Content.Server.Medical.Components;
using Content.Server.PowerCell;
using System.Diagnostics.CodeAnalysis;
using Content.Server.AbstractAnalyzer;
using Content.Server.Body.Components;
using Content.Server.Temperature.Components;
using Content.Shared.Body.Components;
@ -16,7 +14,6 @@ using Content.Shared.Mobs.Components;
using Content.Shared.Popups;
using Content.Shared.PowerCell;
using Content.Shared.Temperature.Components;
using Content.Shared.Traits.Assorted;
using Content.Shared.Nutrition.Components;
using Content.Shared.Nutrition.EntitySystems;
using Robust.Server.GameObjects;
@ -24,6 +21,9 @@ using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Timing;
using Content.Server.Body.Systems;
using Content.Shared.Item.ItemToggle.Components;
using Content.Shared.Interaction.Events;
using Content.Shared.AbstractAnalyzer;
namespace Content.Server.Medical;
@ -31,63 +31,16 @@ public sealed class HealthAnalyzerSystem : AbstractAnalyzerSystem<HealthAnalyzer
{
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly TransformSystem _transformSystem = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
public override void Initialize()
{
SubscribeLocalEvent<HealthAnalyzerComponent, AfterInteractEvent>(OnAfterInteract);
SubscribeLocalEvent<HealthAnalyzerComponent, HealthAnalyzerDoAfterEvent>(OnDoAfter);
SubscribeLocalEvent<HealthAnalyzerComponent, EntGotInsertedIntoContainerMessage>(OnInsertedIntoContainer);
SubscribeLocalEvent<HealthAnalyzerComponent, ItemToggledEvent>(OnToggled);
SubscribeLocalEvent<HealthAnalyzerComponent, DroppedEvent>(OnDropped);
}
public override void Update(float frameTime)
{
var analyzerQuery = EntityQueryEnumerator<HealthAnalyzerComponent, TransformComponent>();
while (analyzerQuery.MoveNext(out var uid, out var component, out var transform))
{
//Update rate limited to 1 second
if (component.NextUpdate > _timing.CurTime)
continue;
if (component.ScannedEntity is not {} patient)
continue;
if (Deleted(patient))
{
StopAnalyzingEntity((uid, component), patient);
continue;
}
component.NextUpdate = _timing.CurTime + component.UpdateInterval;
/// <inheritdoc/>
public override void UpdateScannedUser(EntityUid healthAnalyzer, EntityUid target, bool scanMode)
{
if (args.Target == null || !args.CanReach || !HasComp<MobStateComponent>(args.Target) || !_cell.HasDrawCharge(uid.Owner, user: args.User))
if (!_uiSystem.HasUi(healthAnalyzer, HealthAnalyzerUiKey.Key))
return;
if (!TryComp<DamageableComponent>(target, out var damageableComponent)) // Sunrise-Edit
if (!HasComp<DamageableComponent>(target))
return;
var msg = Loc.GetString("health-analyzer-popup-scan-target", ("user", Identity.Entity(args.User, EntityManager)));
_popupSystem.PopupEntity(msg, args.Target.Value, args.Target.Value, PopupType.Medium);
}
private void OnDoAfter(Entity<HealthAnalyzerComponent> uid, ref HealthAnalyzerDoAfterEvent args)
{
if (args.Handled || args.Cancelled || args.Target == null || !_cell.HasDrawCharge(uid.Owner, user: args.User))
return;
if (healthAnalyzerComp.DamageContainers is not null &&
damageableComponent.DamageContainerID is not null &&
!healthAnalyzerComp.DamageContainers.Contains(damageableComponent.DamageContainerID))
return;
// Sunrise-End
var bodyTemperature = float.NaN;
if (TryComp<TemperatureComponent>(target, out var temp))
@ -101,13 +54,10 @@ public sealed class HealthAnalyzerSystem : AbstractAnalyzerSystem<HealthAnalyzer
_solutionContainerSystem.ResolveSolution(target, bloodstream.BloodSolutionName,
ref bloodstream.BloodSolution, out var bloodSolution))
{
bloodAmount = _bloodstreamSystem.GetBloodLevel(target);
bloodAmount = bloodSolution.FillFraction;
bleeding = bloodstream.BleedAmount > 0;
}
if (TryComp<UnrevivableComponent>(target, out var unrevivableComp) && unrevivableComp.Analyzable)
unrevivable = true;
// Collect hunger and thirst data as percentages
float hungerLevel = -1;
float thirstLevel = -1;
@ -128,6 +78,9 @@ public sealed class HealthAnalyzerSystem : AbstractAnalyzerSystem<HealthAnalyzer
RaiseLocalEvent(target, new EntityAnalyzedEvent ());
// Sunrise edit end
if (TryComp<UnrevivableComponent>(target, out var unrevivableComp) && unrevivableComp.Analyzable)
unrevivable = true;
_uiSystem.ServerSendUiMessage(healthAnalyzer, HealthAnalyzerUiKey.Key, new HealthAnalyzerScannedUserMessage(
GetNetEntity(target),
bodyTemperature,

View file

@ -104,8 +104,8 @@ public sealed class NinjaSuitDrawSystem : SharedNinjaSuitDrawSystem
if (_ninja.GetNinjaBattery(user, out _, out var battery))
{
var canUse = ent.Comp.UseRate <= 0f || battery.CurrentCharge >= ent.Comp.UseRate;
var canDraw = ent.Comp.DrawRate <= 0f || battery.CurrentCharge > 0f;
var canUse = ent.Comp.UseRate <= 0f || battery.ChargeRate >= ent.Comp.UseRate;
var canDraw = ent.Comp.DrawRate <= 0f || battery.ChargeRate > 0f;
SetPowerStatus(ent, canDraw, canUse);
if (!canUse)
{
@ -138,7 +138,7 @@ public sealed class NinjaSuitDrawSystem : SharedNinjaSuitDrawSystem
if (!_ninja.IsNinja(user))
return false;
return _ninja.GetNinjaBattery(user, out _, out var battery) && battery.CurrentCharge > 0f;
return _ninja.GetNinjaBattery(user, out _, out var battery) && battery.ChargeRate > 0f;
}
public override bool CanUse(Entity<NinjaSuitDrawComponent> ent)
@ -148,7 +148,7 @@ public sealed class NinjaSuitDrawSystem : SharedNinjaSuitDrawSystem
return false;
return _ninja.GetNinjaBattery(user, out _, out var battery) &&
(ent.Comp.UseRate <= 0f || battery.CurrentCharge >= ent.Comp.UseRate);
(ent.Comp.UseRate <= 0f || battery.ChargeRate >= ent.Comp.UseRate);
}
}

View file

@ -65,10 +65,6 @@ namespace Content.Server.RoundEnd
/// If the shuttle can't be recalled. if set to true, the station wont be able to recall
/// </summary>
public bool CantRecall = false;
public TimeSpan AutoCallStartTime;
private bool _autoCalledBefore = false;
public override void Initialize()
{
base.Initialize();

View file

@ -259,8 +259,8 @@ public sealed partial class DockingSystem
var spawnPosition = new EntityCoordinates(targetGridXform.MapUid!.Value, _transform.ToMapCoordinates(gridPosition).Position);
// TODO: use tight bounds
var targetWorldAngle = (targetGridAngle + targetAngle).Reduced();
var dockedBounds = new Box2Rotated(shuttleAABB.Translated(spawnPosition.Position), cacheTargetAngle, spawnPosition.Position);
var targetWorldAngle = (targetGridAngle + cacheTargetAngle).Reduced();
var dockedBounds = new Box2Rotated(shuttleAABB.Translated(spawnPosition.Position), targetWorldAngle, spawnPosition.Position);
var grids = new List<Entity<MapGridComponent>>();
_mapManager.FindGridsIntersecting(targetGridXform.MapID, dockedBounds, ref grids, includeMap: false);

View file

@ -8,6 +8,7 @@ using Robust.Server.GameObjects;
using Robust.Server.Player;
using Robust.Server.ServerStatus;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
@ -56,7 +57,7 @@ public sealed class TipsSystem : SharedTipsSystem
private void WatchdogOnUpdateReceived()
{
var message = Loc.GetString("server-updates-received");
SendTippyForAll(message, 5f);
SendTippyForAll(message, null, 5f, 3f, 0.5f);
}
// Sunrise-End
@ -90,11 +91,15 @@ public sealed class TipsSystem : SharedTipsSystem
}
}
public void SendTippyForAll(string msg, float time = 1f)
public void SendTippyForAll(string msg,
EntProtoId? prototype = null,
float speakTime = 1f,
float slideTime = 1f,
float waddleInterval = 1f)
{
var ev = new TippyEvent(msg)
var ev = new TippyEvent(msg, prototype, speakTime, slideTime, waddleInterval)
{
SpeakTime = time + msg.Length * 0.05f
SpeakTime = speakTime + msg.Length * 0.05f
};
RaiseNetworkEvent(ev);
}

View file

@ -127,7 +127,11 @@ public sealed class UplinkSystem : EntitySystem
var pdaUid = containerSlot.ContainedEntity;
// Sunrtise-Start
if (_tagSystem.HasTag(pdaUid.ContainedEntity.Value, "SunriseUplink"))
if (pdaUid == null)
return null;
if (_tagSystem.HasTag(pdaUid.Value, "SunriseUplink"))
continue;
// Sunrtise-End

View file

@ -32,6 +32,7 @@ using System.Diagnostics.CodeAnalysis;
using Content.Shared.Flash;
using Content.Shared.Flash.Components;
using Content.Shared.Storage.Components;
using Content.Shared.Damage.Components;
namespace Content.Server.Vampire;
@ -779,7 +780,7 @@ public sealed partial class VampireSystem
//TODO: Replace with raised event?
if (HasComp<BibleUserComponent>(args.Target))
{
_damageableSystem.TryChangeDamage(entity, VampireComponent.HolyDamage, true);
_damageableSystem.TryChangeDamage(entity.Owner, VampireComponent.HolyDamage, true);
_popup.PopupEntity(Loc.GetString("vampire-ingest-holyblood"), entity, entity, PopupType.LargeCaution);
_admin.Add(LogType.Damaged, LogImpact.Low, $"{ToPrettyString(entity):user} attempted to drink {volumeToConsume}u of {ToPrettyString(args.Target):target}'s holy blood");
return;

View file

@ -34,7 +34,7 @@ public sealed partial class VampireSystem
RemComp<ThirstComponent>(vampire); //Unsure, should vampires thirst.. or hunger?
//Render immune to cold, but not heat
if (TryComp<TemperatureComponent>(vampire, out var temperatureComponent))
if (TryComp<TemperatureDamageComponent>(vampire, out var temperatureComponent))
temperatureComponent.ColdDamageThreshold = Atmospherics.TCMB;
MakeVulnerableToHoly(vampire);

View file

@ -36,6 +36,8 @@ using Content.Shared.Movement.Systems;
using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.StatusEffectNew;
using Content.Shared.StatusEffectNew.Components;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
namespace Content.Server.Vampire;
@ -43,7 +45,6 @@ public sealed partial class VampireSystem : EntitySystem
{
[Dependency] private readonly MindSystem _mind = default!;
[Dependency] private readonly IAdminLogManager _admin = default!;
[Dependency] private readonly FoodSystem _food = default!;
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
[Dependency] private readonly BloodstreamSystem _blood = default!;
[Dependency] private readonly RottingSystem _rotting = default!;
@ -339,7 +340,7 @@ public sealed partial class VampireSystem : EntitySystem
private void DoSpaceDamage(EntityUid uid, VampireComponent comp, DamageableComponent damage)
{
var damageSpec = new DamageSpecifier(_prototypeManager.Index<DamageTypePrototype>("Heat"), 2.5);
_damageableSystem.TryChangeDamage(uid, damageSpec, true, false, damage, uid);
_damageableSystem.TryChangeDamage(uid, damageSpec, true, false, uid);
_popup.PopupEntity(Loc.GetString("vampire-startlight-burning"), uid, uid, PopupType.LargeCaution);
}
private bool IsInSpace(EntityUid vampireUid)

View file

@ -10,6 +10,7 @@ using Content.Shared.Mindshield.Components;
using Content.Shared.Weapons.Melee.Events;
using Content.Shared.Zombies;
using Content.Shared.Weapons.Melee;
using Content.Shared.Damage.Components;
namespace Content.Server.Weapons.Melee.InfectOnMelee;
@ -36,7 +37,7 @@ public sealed class InfectOnMeleeSystem : EntitySystem
&& !_mob.IsDead(entity)
&& _random.Prob(GenerateHitChance(entity, component))
&& !HasComp<ClumsyComponent>(entity)
&& !HasComp<ZombieComponent>(entity)
&& !HasComp<ZombieComponent>(entity)
&& !HasComp<MindShieldComponent>(entity))
{
_audio.PlayPvs(component.InfectionSound, uid);
@ -45,7 +46,7 @@ public sealed class InfectOnMeleeSystem : EntitySystem
}
}
}
private float GenerateHitChance(EntityUid enemy, InfectOnMeleeComponent component)
{
float chance = component.InfectionChance;
@ -59,7 +60,7 @@ public sealed class InfectOnMeleeSystem : EntitySystem
chance = finalChance;
}
return chance;
}
}

View file

@ -1,96 +1,88 @@
using System.Linq;
using System.Numerics;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Components;
using Content.Server.Cargo.Systems;
using Content.Server.Interaction;
using Content.Server.Mech.Equipment.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Weapons.Ranged.Components;
using Content.Server.Stunnable;
using Content.Server.Stunnable.Components;
using Content.Server.Emp;
using Content.Shared.Cargo;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.Effects;
using Content.Shared.Interaction.Components;
using Content.Shared.Mech.Equipment.Components;
using Content.Shared.Projectiles;
using Content.Shared.StatusEffect;
using Content.Shared.Weapons.Melee;
using Content.Shared.Weapons.Ranged;
using Content.Shared.Weapons.Ranged.Components;
using Content.Shared.Weapons.Ranged.Events;
using Content.Shared.Weapons.Ranged.Systems;
using Content.Shared.Weapons.Reflect;
using Content.Shared.Damage.Components;
using Content.Shared.Weapons.Hitscan.Components;
using Content.Shared.Weapons.Hitscan.Events;
using Robust.Shared.Audio;
using Robust.Shared.Map;
using Robust.Shared.Physics;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using Robust.Shared.Containers;
using Content.Shared._Starlight.Weapon.Components;
using Robust.Shared.Physics.Dynamics;
using Content.Shared.Movement.Components;
using Robust.Shared.Random;
using Content.Shared.Decals;
using Content.Server.Body.Components;
using Content.Shared.Chemistry.Reagent;
using Robust.Shared.Timing;
using Content.Server.Decals;
#region Starlight
using System;
using Content.Server.IgnitionSource;
using Content.Server.Atmos.EntitySystems;
using Microsoft.CodeAnalysis.Elfie.Diagnostics;
using Content.Server.Atmos.Components;
using Content.Shared._Starlight.Weapon;
using Robust.Shared.Maths;
using Content.Shared.Pinpointer;
using Robust.Server.GameObjects;
using System.Collections.Generic;
using Content.Server.PowerCell;
using System.Linq;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Components;
using Content.Server.Decals;
using Content.Server.Emp;
using Content.Server.IgnitionSource;
using Content.Server.Interaction;
using Content.Server.Mech.Equipment.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Stunnable.Components;
using Content.Server.Stunnable;
using Content.Shared.Atmos.Components;
using Content.Shared.Body.Components;
using Content.Shared.Cargo;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Damage.Components;
using Content.Shared.Decals;
using Content.Shared.Interaction.Components;
using Content.Shared.Mech.Components;
using Content.Shared.Mech.Equipment.Components;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
using Content.Shared.Pinpointer;
using Content.Shared.Standing;
using Content.Shared.StatusEffect;
using Content.Shared.Stunnable;
using Content.Shared.Weapons.Reflect;
using Content.Shared._Starlight.Weapon.Components;
using Content.Shared._Starlight.Weapon;
using Robust.Server.GameObjects;
using Robust.Shared.Containers;
using Robust.Shared.Maths;
using Robust.Shared.Physics.Dynamics;
using Robust.Shared.Random;
using Robust.Shared.Timing;
#endregion Starlight
namespace Content.Server.Weapons.Ranged.Systems;
public sealed partial class GunSystem : SharedGunSystem
{
[Dependency] private readonly IComponentFactory _factory = default!;
[Dependency] private readonly IRobustRandom _rand = default!; // 🌟Starlight🌟
[Dependency] private readonly BatterySystem _battery = default!;
[Dependency] private readonly DamageExamineSystem _damageExamine = default!;
[Dependency] private readonly PricingSystem _pricing = default!;
[Dependency] private readonly SharedColorFlashEffectSystem _color = default!;
[Dependency] private readonly TransformSystem _transform = default!; // 🌟Starlight🌟
[Dependency] private readonly SharedStaminaSystem _stamina = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
[Dependency] private readonly IPrototypeManager _proto = default!; // 🌟Starlight🌟
[Dependency] private readonly DecalSystem _decals = default!; // 🌟Starlight🌟
[Dependency] private readonly FlammableSystem _flammableSystem = default!; // 🌟Starlight🌟
[Dependency] private readonly AtmosphereSystem _atmosphere = default!; // 🌟Starlight🌟
[Dependency] private readonly StunSystem _stunSystem = default!; // 🌟Starlight🌟
[Dependency] private readonly EmpSystem _emp = default!; // 🌟Starlight🌟
#region Starlight
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly IComponentFactory _factory = default!;
[Dependency] private readonly IRobustRandom _rand = default!;
[Dependency] private readonly BatterySystem _battery = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly DecalSystem _decals = default!;
#endregion Starlight
private const float DamagePitchVariation = 0.05f;
private string[] _bloodDecals = []; // 🌟Starlight🌟
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<BallisticAmmoProviderComponent, PriceCalculationEvent>(OnBallisticPrice);
CacheDecals();
}
private void CacheDecals() // 🌟Starlight🌟
{
_bloodDecals = _proto.EnumeratePrototypes<DecalPrototype>().Where(x => x.Tags.Contains("BloodSplatter")).Select(x => x.ID).ToArray();
}
private void OnBallisticPrice(EntityUid uid, BallisticAmmoProviderComponent component, ref PriceCalculationEvent args)
{
if (string.IsNullOrEmpty(component.Proto) || component.UnspawnedCount == 0)
@ -134,9 +126,8 @@ public sealed partial class GunSystem : SharedGunSystem
? TransformSystem.WithEntityId(fromCoordinates, gridUid)
: new EntityCoordinates(_map.GetMapOrInvalid(fromMap.MapId), fromMap.Position);
var pointerLength = mapDirection.Length(); // 🌟Starlight🌟
// Update shot based on the recoil
toMap = fromMap.Position + (angle.ToVec() * pointerLength); // 🌟Starlight🌟
toMap = fromMap.Position + angle.ToVec() * mapDirection.Length();
mapDirection = toMap - fromMap.Position;
var gunVelocity = Physics.GetMapLinearVelocity(fromEnt);
@ -144,8 +135,6 @@ public sealed partial class GunSystem : SharedGunSystem
// DebugTools.Assert(direction != Vector2.Zero);
var shotProjectiles = new List<EntityUid>(ammo.Count);
bool bulletSoundCheck = false; //starlight
foreach (var (ent, shootable) in ammo)
{
// pneumatic cannon doesn't shoot bullets it just throws them, ignore ammo handling
@ -155,58 +144,9 @@ public sealed partial class GunSystem : SharedGunSystem
continue;
}
// TODO: Clean this up in a gun refactor at some point - too much copy pasting
switch (shootable)
{
//🌟Starlight🌟
case HitScanCartridgeAmmoComponent cartridge:
if (!cartridge.Spent)
{
var hitscanPrototype = ProtoManager.Index(cartridge.Hitscan);
var hitHashSet = new HashSet<EntityUid>();
if (hitscanPrototype.Count > 1)
{
var spread = (hitscanPrototype.Spread + gun.Spread) / 2;
var spreadEvent = new GunGetAmmoSpreadEvent(spread);
RaiseLocalEvent(gunUid, ref spreadEvent);
var angles = LinearSpreadWithRandom(mapAngle - (spreadEvent.Spread / 2),
mapAngle + (spreadEvent.Spread / 2), hitscanPrototype.Count,
3f);
List<List<(EntityCoordinates, float, Angle, EntityUid?)>> hits = new(hitscanPrototype.Count);
for (var i = 0; i < hitscanPrototype.Count; i++)
hits.Add(Hitscan(gunUid, gun, fromCoordinates, user, fromMap, pointerLength, angles[i].ToVec(), hitscanPrototype, hitHashSet));
FireEffects(hits.ToList(), hitscanPrototype);
}
else
{
var hits = Hitscan(gunUid, gun, fromCoordinates, user, fromMap, pointerLength, mapDirection, hitscanPrototype, hitHashSet);
FireEffects([hits], hitscanPrototype);
}
RaiseLocalEvent(ent!.Value, new AmmoShotEvent()
{
FiredProjectiles = shotProjectiles,
});
SetCartridgeSpent(ent!.Value, cartridge, true);
if (cartridge.DeleteOnSpawn)
Del(ent.Value);
}
else
{
userImpulse = false;
Audio.PlayPredicted(gun.SoundEmpty, gunUid, user);
}
// Something like ballistic might want to leave it in the container still
if (!cartridge.DeleteOnSpawn && !Containers.IsEntityInContainer(ent!.Value) && !gun.Pump)
EjectCartridge(ent.Value, angle);
Dirty(ent!.Value, cartridge);
break;
// Cartridge shoots something else
case CartridgeAmmoComponent cartridge:
if (!cartridge.Spent)
@ -243,133 +183,21 @@ public sealed partial class GunSystem : SharedGunSystem
CreateAndFireProjectiles(ent.Value, newAmmo);
break;
case HitscanPrototype hitscan:
case HitscanAmmoComponent:
if (ent == null)
break;
EntityUid? lastHit = null;
List<(EntityCoordinates fromCoordinates, float distance, Angle mapDirection, EntityUid? hitEntity)> effects = [];
var from = fromMap;
// can't use map coords above because funny FireEffects
var fromEffect = fromCoordinates;
var dir = mapDirection.Normalized();
//in the situation when user == null, means that the cannon fires on its own (via signals). And we need the gun to not fire by itself in this case
var lastUser = user ?? gunUid;
if (hitscan.Reflective != ReflectType.None)
var hitscanEv = new HitscanTraceEvent
{
FromCoordinates = fromCoordinates,
ShotDirection = mapDirection.Normalized(),
Gun = gunUid,
Shooter = user,
Target = gun.Targets,
};
RaiseLocalEvent(ent.Value, ref hitscanEv);
for (var reflectAttempt = 0; reflectAttempt < 3; reflectAttempt++)
{
var ray = new CollisionRay(from.Position, dir, hitscan.CollisionMask);
var rayCastResults =
Physics.IntersectRay(from.MapId, ray, hitscan.MaxLength, lastUser, false).ToList();
if (!rayCastResults.Any())
break;
var result = rayCastResults[0];
// Check if laser is shot from in a container
if (!_container.IsEntityOrParentInContainer(lastUser))
{
// Checks if the laser should pass over unless targeted by its user
foreach (var collide in rayCastResults)
{
if (!gun.Targets.Contains(collide.HitEntity) && // Sunrise-Edit
CompOrNull<RequireProjectileTargetComponent>(collide.HitEntity)?.Active == true)
{
continue;
}
result = collide;
break;
}
}
var hit = result.HitEntity;
lastHit = hit;
effects.Add((fromEffect, result.Distance, dir.Normalized().ToAngle(), hit));
var ev = new HitScanReflectAttemptEvent(user, gunUid, hitscan.Reflective, dir, false);
RaiseLocalEvent(hit, ref ev);
if (!ev.Reflected)
break;
fromEffect = Transform(hit).Coordinates;
from = TransformSystem.ToMapCoordinates(fromEffect);
dir = ev.Direction;
lastUser = hit;
}
}
if (lastHit != null)
{
var hitEntity = lastHit.Value;
if (hitscan.StaminaDamage > 0f)
_stamina.TakeStaminaDamage(hitEntity, hitscan.StaminaDamage, source: user);
if (TryComp<StatusEffectsComponent>(hitEntity, out var status))
{
_stunSystem.TryAddParalyzeDuration(hitEntity, TimeSpan.FromSeconds(hitscan.StunAmount));
_stunSystem.TryKnockdown(hitEntity, TimeSpan.FromSeconds(hitscan.KnockdownAmount), true);
}
if (hitscan.Ignite)
{
if (TryComp<FlammableComponent>(hitEntity, out var flammable))
_flammableSystem.SetFireStacks(hitEntity, flammable.FireStacks + (flammable.MinIgnitionTemperature / hitscan.Temperature), flammable, true);
if (Transform(hitEntity) is TransformComponent xform && xform.GridUid is { } hitGridUid)
{
var position = _transform.GetGridOrMapTilePosition(hitEntity, xform);
_atmosphere.HotspotExpose(hitGridUid, position, hitscan.Temperature, 50, user, true);
}
}
if (hitscan.Emp != null)
_emp.EmpPulse(_transform.GetMapCoordinates(hitEntity), hitscan.Emp.Range, hitscan.Emp.EnergyConsumption, TimeSpan.FromSeconds(hitscan.Emp.DisableDuration));
var dmg = hitscan.Damage;
var hitName = ToPrettyString(hitEntity);
if (dmg != null)
dmg = Damageable.TryChangeDamage(hitEntity, dmg, origin: user);
// check null again, as TryChangeDamage returns modified damage values
if (dmg != null)
{
if (!Deleted(hitEntity))
{
if (dmg.AnyPositive())
{
_color.RaiseEffect(Color.Red, new List<EntityUid>() { hitEntity }, Filter.Pvs(hitEntity, entityManager: EntityManager));
}
// TODO get fallback position for playing hit sound.
PlayImpactSound(hitEntity, dmg, hitscan.Sound, hitscan.ForceSound);
}
if (user != null)
{
Logs.Add(LogType.HitScanHit,
$"{ToPrettyString(user.Value):user} hit {hitName:target} using hitscan and dealt {dmg.GetTotal():damage} damage");
}
else
{
Logs.Add(LogType.HitScanHit,
$"{hitName:target} hit by hitscan dealing {dmg.GetTotal():damage} damage");
}
}
}
else
{
effects.Add((fromEffect, hitscan.MaxLength, dir.ToAngle(), null));
}
FireEffects([effects], hitscan);
Del(ent);
Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
break;
@ -386,6 +214,26 @@ public sealed partial class GunSystem : SharedGunSystem
void CreateAndFireProjectiles(EntityUid ammoEnt, AmmoComponent ammoComp)
{
// Startlight-edit: start
var isMechShooter = user != null && TryComp<MechPilotComponent>(user.Value, out _);
const float MechMuzzleOffset = 0.8f;
EntityCoordinates SpawnFrom(Angle angle)
{
if (!isMechShooter)
return fromEnt;
var localAngle = angle;
if (TryComp(fromEnt.EntityId, out TransformComponent? anchorXform))
{
var anchorRot = _transform.GetWorldRotation(anchorXform);
localAngle -= anchorRot;
}
var dir = localAngle.ToVec().Normalized();
return fromEnt.Offset(dir * MechMuzzleOffset);
}
// Startlight-edit: end
if (TryComp<ProjectileSpreadComponent>(ammoEnt, out var ammoSpreadComp))
{
var spreadEvent = new GunGetAmmoSpreadEvent(ammoSpreadComp.Spread);
@ -393,19 +241,35 @@ public sealed partial class GunSystem : SharedGunSystem
var angles = LinearSpread(mapAngle - spreadEvent.Spread / 2,
mapAngle + spreadEvent.Spread / 2, ammoSpreadComp.Count);
// Startlight-edit: start
if (isMechShooter)
{
var spawn = SpawnFrom(angles[0]);
_transform.SetCoordinates(ammoEnt, Transform(ammoEnt), spawn);
}
// Startlight-edit: end
ShootOrThrow(ammoEnt, angles[0].ToVec(), gunVelocity, gun, gunUid, user);
shotProjectiles.Add(ammoEnt);
for (var i = 1; i < ammoSpreadComp.Count; i++)
{
var newuid = Spawn(ammoSpreadComp.Proto, fromEnt);
// Startlight-edit: start
var spawn = isMechShooter ? SpawnFrom(angles[i]) : fromEnt;
var newuid = Spawn(ammoSpreadComp.Proto, spawn);
// Startlight-edit: end
ShootOrThrow(newuid, angles[i].ToVec(), gunVelocity, gun, gunUid, user);
shotProjectiles.Add(newuid);
}
}
else
{
// Startlight-edit: start
if (isMechShooter)
{
var spawn = SpawnFrom(mapDirection.ToAngle());
_transform.SetCoordinates(ammoEnt, Transform(ammoEnt), spawn);
}
// Startlight-edit: end
ShootOrThrow(ammoEnt, mapDirection, gunVelocity, gun, gunUid, user);
shotProjectiles.Add(ammoEnt);
}
@ -413,189 +277,6 @@ public sealed partial class GunSystem : SharedGunSystem
MuzzleFlash(gunUid, ammoComp, mapDirection.ToAngle(), user);
Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
}
//🌟Starlight🌟
// This is fucked already, we need to just comment out the entire Wizden shooting system, take over full maintenance, and rewrite it from scratch.
List<(EntityCoordinates, float, Angle, EntityUid?)> Hitscan
(
EntityUid gunUid,
GunComponent gun,
EntityCoordinates fromCoordinates,
EntityUid? user,
MapCoordinates fromMap,
float pointer,
Vector2 mapDirection,
HitscanPrototype hitscan,
HashSet<EntityUid> hitHashSet
)
{
EntityUid? lastHit = null;
List<(EntityCoordinates fromCoordinates, float distance, Angle mapDirection, EntityUid? hitEntity)> effects = [];
var from = fromMap;
// can't use map coords above because funny FireEffects
var fromEffect = fromCoordinates;
var dir = mapDirection.Normalized();
//in the situation when user == null, means that the cannon fires on its own (via signals). And we need the gun to not fire by itself in this case
var lastUser = user ?? gunUid;
hitHashSet.Clear();
hitHashSet.Add(lastUser);
if (hitscan.Reflective != ReflectType.None)
{
for (var reflectAttempt = 0; reflectAttempt < hitscan.Steps; reflectAttempt++)
{
var ray = new CollisionRay(from.Position, dir, hitscan.CollisionMask);
var rayCastResults = Physics.IntersectRay(from.MapId, ray, hitscan.MaxLength, lastUser, false).ToList();
if (rayCastResults.Count == 0)
break;
var result = rayCastResults[0];
// Check if laser is shot from in a container
if (!_container.IsEntityOrParentInContainer(lastUser))
{
// Checks if the laser should pass over unless targeted by its user
foreach (var collide in rayCastResults)
{
if (!gun.Targets.Contains(collide.HitEntity) && // Sunrise-Edit
CompOrNull<RequireProjectileTargetComponent>(collide.HitEntity)?.Active == true)
continue;
if (collide.Distance < pointer - 2f && HasComp<MobMoverComponent>(collide.HitEntity))
{
if (pointer - collide.Distance > 4f) continue;
var chance = Math.Clamp(1f - ((collide.Distance - 2f) / 2f), 0f, 1f);
if (!_rand.Prob(chance)) continue;
}
if (!hitHashSet.Contains(collide.HitEntity))
hitHashSet.Add(collide.HitEntity);
else
continue;
result = collide;
break;
}
}
var hit = result.HitEntity;
lastHit = hit;
effects.Add((fromEffect, result.Distance, dir.Normalized().ToAngle(), hit));
if (hitscan.Reflective != ReflectType.None)
{
var ev = new HitScanReflectAttemptEvent(user, gunUid, hitscan.Reflective, dir, false);
RaiseLocalEvent(hit, ref ev);
if (ev.Reflected)
{
hitHashSet.Clear();
hitHashSet.Add(hit);
fromEffect = Transform(hit).Coordinates;
from = TransformSystem.ToMapCoordinates(fromEffect);
dir = ev.Direction;
lastUser = hit;
continue;
}
}
if (hitscan.RicochetChance > 0f)
{
var ev = new HitScanRicochetAttemptEvent(hitscan.RicochetChance, from.Position, dir, false);
RaiseLocalEvent(hit, ref ev);
if (ev.Ricocheted)
{
hitHashSet.Clear();
hitHashSet.Add(hit);
fromEffect = _transform.ToCoordinates(result.HitEntity, new MapCoordinates(result.HitPos, fromMap.MapId));
from = TransformSystem.ToMapCoordinates(fromEffect);
dir = ev.Dir;
lastUser = hit;
continue;
}
}
Hit(user, hitscan, lastHit.Value);
if (hitscan.PierceChance >= 1f || (hitscan.PierceChance > 0f && _rand.Prob(hitscan.PierceChance)))
{
var ev = new HitScanPierceAttemptEvent(hitscan.PierceLevel, true);
RaiseLocalEvent(hit, ref ev);
if (ev.Pierced)
{
var random = Random.NextFloat(-hitscan.Derivation, hitscan.Derivation);
fromEffect = _transform.ToCoordinates(result.HitEntity, new MapCoordinates(result.HitPos, fromMap.MapId));
from = TransformSystem.ToMapCoordinates(fromEffect);
dir = (dir.ToAngle() + random).ToVec();
lastUser = hit;
continue;
}
}
break;
}
if (lastHit == null)
effects.Add((fromEffect, hitscan.MaxLength, dir.ToAngle(), null));
}
// Starlight confirm bullet sound should play
bulletSoundCheck = true;
return effects;
void Hit(EntityUid? user, HitscanPrototype hitscan, EntityUid hitEntity)
{
if (Deleted(hitEntity)) return;
if (hitscan.StaminaDamage > 0f)
_stamina.TakeStaminaDamage(hitEntity, hitscan.StaminaDamage, source: user);
var dmg = hitscan.Damage;
var hitName = ToPrettyString(hitEntity);
if (dmg != null)
dmg = Damageable.TryChangeDamage(
hitEntity,
dmg,
ignoreResistances: hitscan.IgnoreResistances,
origin: user,
armorPenetration: hitscan.ArmorPenetration,
canHeal: false
);
// check null again, as TryChangeDamage returns modified damage values
if (dmg != null)
{
if (dmg.AnyPositive())
{
_color.RaiseEffect(Color.Red, [hitEntity], Filter.Pvs(hitEntity, entityManager: EntityManager));
}
// TODO get fallback position for playing hit sound.
PlayImpactSound(hitEntity, dmg, hitscan.Sound, hitscan.ForceSound);
if (user != null)
{
Logs.Add(LogType.HitScanHit,
$"{ToPrettyString(user.Value):user} hit {hitName:target} using hitscan and dealt {dmg.GetTotal():damage} damage");
}
else
{
Logs.Add(LogType.HitScanHit,
$"{hitName:target} hit by hitscan dealing {dmg.GetTotal():damage} damage");
}
}
}
}
//starlight check to see if bullet sound should play
if (bulletSoundCheck){
Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
}
}
private void ShootOrThrow(EntityUid uid, Vector2 mapDirection, Vector2 gunVelocity, GunComponent gun, EntityUid gunUid, EntityUid? user)
@ -607,6 +288,24 @@ public sealed partial class GunSystem : SharedGunSystem
Dirty(uid, targeted);
}
// Starlight start - cartridges can hold hitscans
if (HasComp<HitscanAmmoComponent>(uid))
{
var hitscanEv = new HitscanTraceEvent
{
FromCoordinates = EntityManager.GetComponent<TransformComponent>(uid).Coordinates,
ShotDirection = mapDirection.Normalized(),
Gun = gunUid,
Shooter = user,
Target = gun.Targets,
};
RaiseLocalEvent(uid, ref hitscanEv);
Del(uid);
return;
}
// Starlight end - cartridges can hold hitscans
// Do a throw
if (!HasComp<ProjectileComponent>(uid))
{
@ -686,7 +385,7 @@ public sealed partial class GunSystem : SharedGunSystem
RaiseNetworkEvent(message, filter);
}
public void PlayImpactSound(EntityUid otherEntity, DamageSpecifier? modifiedDamage, SoundSpecifier? weaponSound, bool forceWeaponSound)
public override void PlayImpactSound(EntityUid otherEntity, DamageSpecifier? modifiedDamage, SoundSpecifier? weaponSound, bool forceWeaponSound)
{
DebugTools.Assert(!Deleted(otherEntity), "Impact sound entity was deleted");
@ -717,102 +416,4 @@ public sealed partial class GunSystem : SharedGunSystem
Audio.PlayPvs(weaponSound, otherEntity);
}
}
// TODO: Pseudo RNG so the client can predict these.
#region Hitscan effects
// 🌟Starlight🌟
private void FireEffects(List<List<(EntityCoordinates fromCoordinates, float distance, Angle angle, EntityUid? hitEntity)>> hits, HitscanPrototype hitscan)
{
if (hits.Count == 0) return;
var hitscanEvent = new HitscanEvent
{
Hitscan = hitscan.ID,
Effects = new Effect[hits.Count][]
};
var spreadIndex = -1;
HashSet<EntityCoordinates> pvs = [];
foreach (var hit in hits)
{
spreadIndex++;
var index = -1;
hitscanEvent.Effects[spreadIndex] = new Effect[hit.Count];
ref var effects = ref hitscanEvent.Effects[spreadIndex];
foreach (var item in hit)
{
var (fromCoordinates, distance, angle, hitEntity) = item;
var fromXform = Transform(fromCoordinates.EntityId);
var gridUid = fromXform.GridUid;
if (gridUid != fromCoordinates.EntityId && TryComp(gridUid, out TransformComponent? gridXform))
{
var (_, gridRot, gridInvMatrix) = TransformSystem.GetWorldPositionRotationInvMatrix(gridXform);
var map = _transform.ToMapCoordinates(fromCoordinates);
fromCoordinates = new EntityCoordinates(gridUid.Value, Vector2.Transform(map.Position, gridInvMatrix));
angle -= gridRot;
}
else
{
angle -= _transform.GetWorldRotation(fromXform);
}
index++;
effects[index] = new Effect
{
Angle = angle,
Distance = distance,
};
ref var effect = ref effects[index];
if (distance >= 1f)
{
var muzzleCoords = fromCoordinates.Offset(angle.ToVec().Normalized() / 2);
var travelCoords = fromCoordinates.Offset(angle.ToVec() * (distance + 0.5f) / 2);
effect.MuzzleCoordinates = GetNetCoordinates(muzzleCoords);
effect.TravelCoordinates = GetNetCoordinates(travelCoords);
}
var impactCoords = fromCoordinates.Offset(angle.ToVec() * distance);
effect.ImpactCoordinates = GetNetCoordinates(impactCoords);
if (hitEntity is not null)
{
if (hitscan.Reflective == ReflectType.NonEnergy)
{
if (TryComp<BloodstreamComponent>(hitEntity, out var bloodstream))
{
Timer.Spawn(200, () =>
{
var color = _proto.Index(bloodstream.BloodReagent).SubstanceColor;
// A flash of the neuralyzer, then a man in a black suit says that you didnt see any “vector crutch” here, and if you did—read it again.
var coords = fromCoordinates.Offset((angle.ToVec() * (distance + 1.3f)) + new Vector2(-0.5f, -0.5f));
_decals.TryAddDecal(_rand.Pick(_bloodDecals), coords, out _, color, angle + Angle.FromDegrees(-45), cleanable: true);
});
}
else
{
effect.ImpactEnt = GetNetEntity(hitEntity.Value);
}
}
}
pvs.Add(fromCoordinates);
}
}
if (pvs.Count > 0)
{
var filter = Filter.Empty();
foreach (var pos in pvs.Where(x => x.IsValid(EntityManager)))
filter.Merge(Filter.Pvs(pos, entityMan: EntityManager));
RaiseNetworkEvent(hitscanEvent, filter);
}
}
#endregion
}

View file

@ -10,6 +10,8 @@ using Content.Shared.Mobs.Components;
using Content.Shared._Starlight.Actions.Stasis;
using Content.Shared.Body.Components;
using Robust.Shared.Player;
using Content.Shared.Damage.Systems;
using Content.Shared.Damage.Components;
namespace Content.Server._Starlight.Actions.Stasis;

View file

@ -9,6 +9,7 @@ using Content.Shared._Starlight.Combat.Ranged.Pierce;
using Content.Shared.Armor;
using Content.Shared.Damage;
using Content.Shared.Inventory;
using Content.Shared.Weapons.Hitscan.Events;
namespace Content.Server._Starlight.Combat.Ranged;

View file

@ -6,7 +6,9 @@ using Content.Server.Radio.EntitySystems;
using Content.Shared.Abilities.Goliath;
using Content.Shared.Atmos;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.Ghost;
using Content.Shared.Interaction;
using Content.Shared.Projectiles;

View file

@ -1,6 +1,8 @@
using Content.Server.Humanoid;
using Content.Shared._Sunrise.Antags.Abductor;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Eye.Blinding.Components;
using Content.Shared.Eye.Blinding.Systems;
using Content.Shared.Speech.Muting;
@ -58,9 +60,9 @@ public sealed partial class OrganSystem : EntitySystem
{
if (!TryComp<DamageableComponent>(args.Body, out var bodyDamageable)) return;
var change = _damageableSystem.TryChangeDamage(args.Body, ent.Comp.Damage, true, false, bodyDamageable);
var change = _damageableSystem.ChangeDamage(args.Body, ent.Comp.Damage, true, false);
if (change is not null)
_damageableSystem.TryChangeDamage(ent.Owner, change.Invert(), true, false, ent.Comp);
_damageableSystem.ChangeDamage(ent.Owner, change.Invert(), true, false);
}
private void OnOrganExtracted(Entity<DamageableComponent> ent, ref SurgeryOrganExtracted args)
{
@ -68,11 +70,10 @@ public sealed partial class OrganSystem : EntitySystem
|| damageRule.Damage is null
|| !TryComp<DamageableComponent>(args.Body, out var bodyDamageable)) return;
var change = _damageableSystem.TryChangeDamage(args.Body, damageRule.Damage.Invert(), true, false, bodyDamageable);
var change = _damageableSystem.ChangeDamage(args.Body, damageRule.Damage.Invert(), true, false);
if (change is not null)
_damageableSystem.TryChangeDamage(ent.Owner, change.Invert(), true, false, ent.Comp);
_damageableSystem.ChangeDamage(ent.Owner, change.Invert(), true, false);
}
private void OnTongueImplanted(Entity<OrganTongueComponent> ent, ref SurgeryOrganImplantationCompleted args)
{
if (HasComp<AbductorComponent>(args.Body) || !ent.Comp.IsMuted) return;

View file

@ -13,12 +13,14 @@ using Content.Shared.Traits.Assorted;
using Microsoft.CodeAnalysis;
using Content.Server._Starlight.Medical.Limbs;
using Content.Server.Administration.Systems;
using Content.Shared.Bed.Sleep;
using Content.Shared.Damage.Components;
namespace Content.Server.Starlight.Medical.Surgery;
// Based on the RMC14.
// https://github.com/RMC-14/RMC-14
//
//
//This file is already overloaded with responsibilities,
//its time to break its functionality into different systems.
//However, I dont want to touch the official systems, so I need to come up with extensions for them.
@ -27,6 +29,7 @@ public sealed partial class SurgerySystem : SharedSurgerySystem
[Dependency] private readonly IComponentFactory _compFactory = default!;
[Dependency] private readonly LimbSystem _limbSystem = default!;
[Dependency] private readonly StarlightEntitySystem _entity = default!;
[Dependency] private readonly SleepingSystem _sleeping = default!;
public void InitializeSteps()
{
@ -135,11 +138,11 @@ public sealed partial class SurgerySystem : SharedSurgerySystem
private void OnStepEmoteEffectComplete(Entity<SurgeryStepEmoteEffectComponent> ent, ref SurgeryStepEvent args)
{
if (!HasComp<PainNumbnessComponent>(args.Body))
{
_chat.TryEmoteWithChat(args.Body, ent.Comp.Emote);
}
if (!HasComp<PainNumbnessStatusEffectComponent>(args.Body) && !HasComp<SleepingComponent>(args.Body))
_chat.TryEmoteWithChat(args.Body, ent.Comp.Emote);
else
_sleeping.TryWaking(args.Body); // If the patient sleeping without n2o or reagents, wake them up.
}
private void OnStepSpawnComplete(Entity<SurgeryStepSpawnEffectComponent> ent, ref SurgeryStepEvent args)
@ -148,7 +151,7 @@ public sealed partial class SurgerySystem : SharedSurgerySystem
SpawnAtPosition(ent.Comp.Entity, xform.Coordinates);
}
private void OnStepAttachLimbComplete(Entity<SurgeryStepAttachLimbEffectComponent> _, string slot, ref SurgeryStepEvent args)
private void OnStepAttachLimbComplete(Entity<SurgeryStepAttachLimbEffectComponent> _, string slot, ref SurgeryStepEvent args)
=> args.IsCancelled = args.Tools.Count == 0
|| !(args.Tools.FirstOrDefault() is var limdId)
|| !TryComp<BodyPartComponent>(limdId, out var limb)
@ -157,16 +160,16 @@ public sealed partial class SurgerySystem : SharedSurgerySystem
|| !_limbSystem.AttachLimb((args.Body, humanoid), slot, (args.Part, part), (limdId, limb));
private void OnStepAttachItemComplete(Entity<SurgeryStepAttachLimbEffectComponent> ent, string slot, ref SurgeryStepEvent args)
=> args.IsCancelled = args.Tools.Count == 0
|| !(args.Tools.FirstOrDefault() is var itemId)
|| !TryComp(itemId, out MetaDataComponent? metadata)
|| HasComp<BodyPartComponent>(itemId)
|| !TryComp(args.Part, out BodyPartComponent? limb)
=> args.IsCancelled = args.Tools.Count == 0
|| !(args.Tools.FirstOrDefault() is var itemId)
|| !TryComp(itemId, out MetaDataComponent? metadata)
|| HasComp<BodyPartComponent>(itemId)
|| !TryComp(args.Part, out BodyPartComponent? limb)
|| !_limbSystem.AttachItem(args.Body, slot, (args.Part, limb), (itemId, metadata));
private void OnStepAmputationComplete(Entity<SurgeryStepAmputationEffectComponent> ent, ref SurgeryStepEvent args)
{
if (_entity.TryEntity<TransformComponent, HumanoidAppearanceComponent, BodyComponent>(args.Body, out var body)
if (_entity.TryEntity<TransformComponent, HumanoidAppearanceComponent, BodyComponent>(args.Body, out var body)
&& _entity.TryEntity<TransformComponent, MetaDataComponent, BodyPartComponent>(args.Part, out var limb))
_limbSystem.Amputatate(body, limb);
}

View file

@ -14,6 +14,7 @@ using Robust.Server.GameObjects;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using Content.Server.Administration.Systems;
using Content.Shared.Damage.Systems;
namespace Content.Server.Starlight.Medical.Surgery;
// Based on the RMC14.

View file

@ -17,6 +17,7 @@ using Content.Shared.Wieldable;
using Content.Shared.Weapons.Ranged.Components;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Map;
using Content.Shared.Damage.Systems;
namespace Content.Server._Starlight.Weapon.Systems;
public sealed partial class WeaponDismantleOnShootSystem : SharedWeaponDismantleOnShootSystem
@ -43,9 +44,12 @@ public sealed partial class WeaponDismantleOnShootSystem : SharedWeaponDismantle
if (DismantleCheck(ent, ref args) == false)
return;
if (!args.Shooter.HasValue)
return;
//apply the damage to the shooter
//get the shooters damageable component
Damageable.TryChangeDamage(args.Shooter, ent.Comp.SelfDamage, origin:args.Shooter);
Damageable.TryChangeDamage(args.Shooter.Value, ent.Comp.SelfDamage, origin: args.Shooter.Value);
//we need the user past this point
if (!args.Shooter.HasValue)
@ -58,7 +62,7 @@ public sealed partial class WeaponDismantleOnShootSystem : SharedWeaponDismantle
if (!TryComp<GunComponent>(ent, out var gunComponent))
return;
var toCoordinates = gunComponent.ShootCoordinates;
if (toCoordinates == null)

View file

@ -6,6 +6,7 @@ using Content.Shared.Chat;
using Content.Shared.Chat.Prototypes;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.Emoting;
using Content.Shared.Gravity;
using Content.Shared.Standing;
@ -88,7 +89,7 @@ public sealed class EmoteAnimationSystem : EntitySystem
if (emoteId == "FallOnNeck")
{
var damage = new DamageSpecifier(_prototypeManager.Index<DamageTypePrototype>("Blunt"), 100);
_damageableSystem.TryChangeDamage(uid, damage, true, useVariance: false, useModifier: false);
_damageableSystem.ChangeDamage(uid, damage, true, useVariance: false, ignoreGlobalModifiers: true);
}
component.AnimationId = emoteId;

View file

@ -23,6 +23,7 @@ using Content.Shared.Humanoid;
using System.Diagnostics.CodeAnalysis;
using Content.Shared._Sunrise.Drugs;
using Content.Shared.Anomaly.Components;
using Content.Shared.Damage.Systems;
namespace Content.Server._Sunrise.Anomaly.Systems;

View file

@ -22,6 +22,7 @@ using Content.Shared._Sunrise.VentCraw;
using Content.Shared.CombatMode.Pacification;
using Content.Shared.Starlight.Medical.Surgery.Events;
using Content.Server.Objectives.Components;
using Content.Shared.Damage.Systems;
namespace Content.Server._Sunrise.Antags.Abductor;

View file

@ -1,5 +1,7 @@
using System.Linq;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Mobs.Systems;
using Content.Shared.Whitelist;
using Robust.Shared.Timing;
@ -45,7 +47,7 @@ public sealed class AoEHealSystem : EntitySystem
target.Comp.Damage.GetTotal() < threshold * (1f - aoEHealComponent.Threshold)) // Не лечим если урона мало
continue;
_damageableSystem.TryChangeDamage(target, aoEHealComponent.Damage);
_damageableSystem.TryChangeDamage(target.Owner, aoEHealComponent.Damage);
}
}
}

View file

@ -8,6 +8,7 @@ using Content.Shared.Body.Systems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Content.Shared.Interaction;
using Content.Shared.Mobs.Components;

View file

@ -7,6 +7,7 @@ using Content.Shared._Sunrise.BloodCult.Items;
using Content.Shared.Actions;
using Content.Shared.Actions.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Mobs.Components;
using Content.Shared.Popups;
using Content.Shared.Stunnable;

View file

@ -10,7 +10,9 @@ using Content.Shared.Body.Components;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.Examine;
using Content.Shared.FixedPoint;
using Content.Shared.Fluids.Components;

View file

@ -1,6 +1,8 @@
using Content.Server._Sunrise.BloodCult.Items.Components;
using Content.Shared._Sunrise.BloodCult.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Inventory.Events;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;

View file

@ -6,6 +6,8 @@ using Content.Shared._Sunrise.BloodCult.Components;
using Content.Shared._Sunrise.BloodCult.Pylon;
using Content.Shared.Body.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Doors.Components;
using Content.Shared.Interaction;
using Content.Shared.Maps;
@ -210,7 +212,7 @@ public sealed class PylonSystem : EntitySystem
_blood.TryModifyBleedAmount((playerEntity, bloodstream), -comp.BleedReductionAmount);
}
if (_blood.GetBloodLevelPercentage((playerEntity, bloodstream)) < bloodstream.BloodMaxVolume)
if (_blood.GetBloodLevel((playerEntity, bloodstream)) < bloodstream.BloodReferenceSolution.MaxVolume)
{
_blood.TryModifyBloodLevel((playerEntity, bloodstream), comp.BloodRefreshAmount);
}

View file

@ -381,7 +381,7 @@ namespace Content.Server._Sunrise.BloodCult.Runes.Systems
if (!_entityManager.TryGetComponent<StackComponent>(material, out var stackNew))
return;
stackNew.Count = count;
_stack.SetCount((material, stackNew), count);
_popupSystem.PopupEntity(Loc.GetString($"Пласталь превращается в {MetaData(material).EntityName}!"),
args.Performer,

View file

@ -18,6 +18,7 @@ using Content.Shared._Sunrise.BloodCult.Runes;
using Content.Shared._Sunrise.BloodCult.UI;
using Content.Shared.Atmos.Components;
using Content.Shared.Body.Components;
using Content.Shared.Chat;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Coordinates;
using Content.Shared.Cuffs.Components;
@ -564,7 +565,7 @@ namespace Content.Server._Sunrise.BloodCult.Runes.Systems
HealCultist(target);
if (TryComp<CuffableComponent>(target, out var cuffs) && cuffs.Container.ContainedEntities.Count >= 1)
_cuffable.Uncuff(target, cuffs.LastAddedCuffs, cuffs.LastAddedCuffs);
_cuffable.Uncuff(target, cuffs.Container.ContainedEntities[^1], cuffs.Container.ContainedEntities[^1]);
return true;
}

View file

@ -20,6 +20,7 @@ using Content.Shared.Alert;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Inventory;
using Content.Shared.Maps;
using Content.Shared.Movement.Pulling.Systems;
@ -54,6 +55,7 @@ namespace Content.Server._Sunrise.BloodCult.Runes.Systems
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly EmpSystem _empSystem = default!;
[Dependency] private readonly EntityManager _entityManager = default!;
[Dependency] private readonly SharedStackSystem _stack = default!;
[Dependency] private readonly EuiManager _euiManager = default!;
[Dependency] private readonly FlammableSystem _flammableSystem = default!;
[Dependency] private readonly FlashSystem _flashSystem = default!;

View file

@ -2,6 +2,7 @@
using Content.Shared._Sunrise.BloodCult.Components;
using Content.Shared._Sunrise.BloodCult.Structures;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Doors;
using Content.Shared.Stunnable;
using Content.Shared.Throwing;

View file

@ -1,6 +1,8 @@
using Content.Shared._Sunrise.Boss.Components;
using Content.Shared._Sunrise.Boss.Systems;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Throwing;
using Content.Shared.Whitelist;
using Robust.Shared.Physics.Components;
@ -54,7 +56,7 @@ public sealed class DamageOnCollideSystem : SharedDamageOnCollideSystem
public void Damage(EntityUid uid, DamageOnCollideComponent component)
{
if (_whitelist.IsBlacklistPass(component.Blacklist, uid))
if (_whitelist.IsWhitelistFail(component.Blacklist, uid))
return;
_damageable.TryChangeDamage(uid, component.Damage);
}

View file

@ -3,6 +3,7 @@ using Content.Shared._Sunrise.Boss.Systems;
using Content.Shared.Actions;
using Content.Shared.Actions.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Robust.Shared.Timing;
namespace Content.Server._Sunrise.Boss.Systems;

View file

@ -4,6 +4,8 @@ using Content.Shared._Sunrise.Boss.Events;
using Content.Shared.Actions;
using Content.Shared.Camera;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Throwing;
using Content.Shared.Whitelist;
using Robust.Shared.Audio.Systems;
@ -61,9 +63,9 @@ public sealed class HellSpawnRushSystem : EntitySystem
var query = _lookup.GetEntitiesInRange<DamageableComponent>(Transform(ent.Owner).Coordinates, 1.3f);
foreach (var entity in query)
{
if (_whitelist.IsBlacklistPass(ent.Comp.Blacklist, entity))
if (_whitelist.IsWhitelistFail(ent.Comp.Blacklist, entity))
continue;
_damageable.TryChangeDamage(entity, ent.Comp.ThrowHitDamageDict);
_damageable.TryChangeDamage(entity.Owner, ent.Comp.ThrowHitDamageDict);
}
QueueDel(ent.Comp.RuneUid);

View file

@ -18,6 +18,8 @@ using Content.Shared.NPC.Systems;
using Content.Shared.Nutrition.Components;
using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Chat;
namespace Content.Server._Sunrise.CarpQueen;

View file

@ -49,7 +49,7 @@ public sealed class CarpServantBiteSystem : EntitySystem
if (solution.Volume > FixedPoint2.Zero)
{
_bloodstream.TryAddToChemicals((target, bloodstream), solution);
_bloodstream.TryAddToBloodstream((target, bloodstream), solution);
}
}
}

View file

@ -1,6 +1,7 @@
using Content.Shared._Sunrise.CarpQueen;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Mobs.Components;
using Content.Shared.NPC.Components;
using Content.Shared.NPC.Systems;

View file

@ -1,4 +1,5 @@
using Content.Server.Botany.Components;
using Content.Shared.Botany.Components;
using Content.Shared.CartridgeLoader;
using Robust.Server.GameObjects;

View file

@ -1,4 +1,5 @@
using Content.Server.Chat.Systems;
using Content.Shared.Chat;
namespace Content.Server._Sunrise.Chat.Sanitization;

View file

@ -1,5 +1,6 @@
using Content.Server.Chat.Systems;
using Content.Shared._Sunrise.SunriseCCVars;
using Content.Shared.Chat;
using Content.Shared.GameTicking;
using Content.Shared.Popups;
using Content.Shared.Speech.Muting;

View file

@ -1,4 +1,5 @@
using Content.Server.Chat.Systems;
using Content.Shared.Chat;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;

View file

@ -2,6 +2,7 @@ using Content.Server.Popups;
using Content.Shared._Sunrise.DamageOverlay;
using Content.Shared._Sunrise.Helpers;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Content.Shared.GameTicking;
using Robust.Shared.Map;

View file

@ -30,7 +30,12 @@ public sealed class DiseaseRoleSystem : SharedDiseaseRoleSystem
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
private static readonly string[] _bloodReagents = { "DiseaseBloodFirst", "DiseaseBloodSecond", "DiseaseBloodThird" };
private static readonly List<string> _bloodReagents = new()
{
"DiseaseBloodFirst",
"DiseaseBloodSecond",
"DiseaseBloodThird"
};
[ValidatePrototypeId<EntityPrototype>] private const string DiseaseShopId = "ActionDiseaseShop";
@ -87,7 +92,7 @@ public sealed class DiseaseRoleSystem : SharedDiseaseRoleSystem
_sharedCharges.SetCharges((actionId.Value, limitCharges), charges);
}
}
component.NewBloodReagent = _random.Pick(_bloodReagents);
component.NewBloodReagent.Add(_random.Pick(_bloodReagents));
component.Symptoms.Add("Headache", new SymptomData(1, 4));
}

View file

@ -32,6 +32,8 @@ using Content.Shared.Item;
using Content.Shared.Medical;
using Content.Shared.Speech.Muting;
using Content.Shared.Store.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Chemistry.Components;
namespace Content.Server._Sunrise.Disease;
public sealed class SickSystem : SharedSickSystem
{
@ -103,10 +105,17 @@ public sealed class SickSystem : SharedSickSystem
}
}
if (!string.IsNullOrEmpty(component.BeforeInfectedBloodReagent) &&
TryComp<BloodstreamComponent>(uid, out var bloodstream))
if (TryComp<BloodstreamComponent>(uid, out var stream))
{
_bloodstream.ChangeBloodReagent(uid, component.BeforeInfectedBloodReagent);
var solution = new Solution();
foreach (var reagentId in component.BeforeInfectedBloodReagent)
{
// Количество подставь логичное для твоей механики
solution.AddReagent(reagentId, FixedPoint2.New((int)stream.BloodReferenceSolution.MaxVolume));
}
_bloodstream.ChangeBloodReagents(uid, solution);
}
}
public override void Update(float frameTime)
@ -124,10 +133,22 @@ public sealed class SickSystem : SharedSickSystem
UpdateInfection(uid, component, component.owner, diseaseComp);
if (!component.Inited)
{
//Infect
if (TryComp<BloodstreamComponent>(uid, out var stream))
component.BeforeInfectedBloodReagent = stream.BloodReagent;
_bloodstream.ChangeBloodReagent(uid, diseaseComp.NewBloodReagent);
{
foreach (var item in stream.BloodReferenceSolution)
{
component.BeforeInfectedBloodReagent.Add(item.Reagent.Prototype);
}
var solution = new Solution();
foreach (var reagentId in diseaseComp.NewBloodReagent)
{
// количество — подставь нужное тебе
solution.AddReagent(reagentId, FixedPoint2.New((int)stream.BloodReferenceSolution.MaxVolume));
}
_bloodstream.ChangeBloodReagents(uid, solution);
}
RaiseNetworkEvent(new ClientInfectEvent(GetNetEntity(uid), GetNetEntity(component.owner)));
diseaseComp.SickOfAllTime++;

View file

@ -7,6 +7,7 @@ using Content.Shared.Popups;
using Content.Shared.Power.Components;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Content.Shared.Damage.Systems;
namespace Content.Server._Sunrise.EnergyShield;
@ -40,10 +41,10 @@ public sealed class EnergyShieldSystem : EntitySystem
return;
var cost = totalDamage.Float() * ent.Comp.EnergyCostPerDamage;
_battery.UseCharge(ent, cost, battery);
_battery.UseCharge(ent.Owner, cost);
_audio.PlayPvs(ent.Comp.AbsorbSound, ent);
if (battery.CurrentCharge <= 0)
if (battery.ChargeRate <= 0)
{
_itemToggle.Toggle(ent.Owner);
_audio.PlayPvs(ent.Comp.ShutdownSound, ent);
@ -53,7 +54,7 @@ public sealed class EnergyShieldSystem : EntitySystem
private void OnToggleAttempt(Entity<EnergyShieldComponent> ent, ref ItemToggleActivateAttemptEvent args)
{
if (TryComp<BatteryComponent>(ent, out var battery) &&
battery.CurrentCharge >= battery.MaxCharge * ent.Comp.MinChargeFractionForActivation)
battery.ChargeRate >= battery.MaxCharge * ent.Comp.MinChargeFractionForActivation)
{
return;
}

View file

@ -23,6 +23,8 @@ using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Containers;
using Content.Shared.Silicons.Borgs.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Damage.Components;
namespace Content.Server._Sunrise.Execution;
@ -289,7 +291,7 @@ public sealed class ExecutionSystem : EntitySystem
if (!TryComp<MeleeWeaponComponent>(weapon, out var melee) && melee!.Damage.GetTotal() > 0.0f)
return;
_damageableSystem.TryChangeDamage(victim, melee.Damage * DamageModifier, true, useVariance: false, useModifier: false);
_damageableSystem.ChangeDamage(victim, melee.Damage * DamageModifier, true, useVariance: false, ignoreGlobalModifiers: true);
_audioSystem.PlayEntity(melee.HitSound, Filter.Pvs(weapon), weapon, true, AudioParams.Default);
if (attacker == victim)
@ -414,7 +416,7 @@ public sealed class ExecutionSystem : EntitySystem
}
// Gun successfully fired, deal damage
_damageableSystem.TryChangeDamage(victim, damage * DamageModifier, true, useVariance: false, useModifier: false);
_damageableSystem.ChangeDamage(victim, damage * DamageModifier, true, useVariance: false, ignoreGlobalModifiers: true);
_audioSystem.PlayEntity(component.SoundGunshot, Filter.Pvs(weapon), weapon, false, AudioParams.Default);
// Popups

View file

@ -6,6 +6,7 @@ using Content.Shared.Clothing;
using Content.Shared.Clothing.Components;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Mobs;

View file

@ -157,14 +157,17 @@ public sealed partial class FleshCultSystem
}
else
{
if (!component.BloodWhitelist.Contains(bloodstream.BloodReagent))
foreach (var reagent in bloodstream.BloodReferenceSolution.Contents)
{
_popup.PopupEntity(
Loc.GetString("flesh-cultist-devout-target-not-have-flesh"),
uid, uid);
return;
if (!component.BloodWhitelist.Contains(reagent.Reagent.Prototype))
{
_popup.PopupEntity(
Loc.GetString("flesh-cultist-devout-target-not-have-flesh"),
uid, uid);
return;
}
}
if (bloodstream.BloodMaxVolume < 30)
if ((int)bloodstream.BloodReferenceSolution.MaxVolume < 30)
{
_popup.PopupEntity(
Loc.GetString("flesh-cultist-devout-target-invalid"),
@ -172,7 +175,7 @@ public sealed partial class FleshCultSystem
return;
}
}
var saturation = MatchSaturation(bloodstream.BloodMaxVolume.Value / 100, hasAppearance);
var saturation = MatchSaturation((int)bloodstream.BloodReferenceSolution.MaxVolume / 100, hasAppearance);
if (TryComp<FleshCultistComponent>(uid, out var fleshCultistComponent) &&
fleshCultistComponent.Hunger + saturation >= fleshCultistComponent.MaxHunger)
{
@ -290,9 +293,9 @@ public sealed partial class FleshCultSystem
hasAppearance = true;
}
var saturation = MatchSaturation(bloodstream.BloodMaxVolume.Value / 100, hasAppearance);
var evolutionPoint = MatchEvolutionPoint(bloodstream.BloodMaxVolume.Value / 100, hasAppearance);
var healPoint = MatchHealPoint(bloodstream.BloodMaxVolume.Value / 100, hasAppearance);
var saturation = MatchSaturation((int)bloodstream.BloodReferenceSolution.MaxVolume / 100, hasAppearance);
var evolutionPoint = MatchEvolutionPoint((int)bloodstream.BloodReferenceSolution.MaxVolume / 100, hasAppearance);
var healPoint = MatchHealPoint((int)bloodstream.BloodReferenceSolution.MaxVolume / 100, hasAppearance);
RemComp<BloodstreamComponent>(args.Args.Target.Value);
@ -418,7 +421,7 @@ public sealed partial class FleshCultSystem
if (TryComp<CuffableComponent>(uid, out var cuffableComponent) && cuffableComponent.CuffedHandCount > 0)
{
_cuffable.Uncuff(uid, uid, cuffableComponent.LastAddedCuffs);
_cuffable.Uncuff(uid, uid, cuffableComponent.Container.ContainedEntities[^1]);
}
foreach (var hand in _handsSystem.EnumerateHands(uid))

View file

@ -270,7 +270,7 @@ public sealed partial class FleshCultSystem
private void OnColdTempImmunityMutation(EntityUid uid, FleshCultistComponent component, FleshCultistColdTempImmunityMutationEvent args)
{
if (TryComp<TemperatureComponent>(uid, out var tempComponent))
if (TryComp<TemperatureDamageComponent>(uid, out var tempComponent))
tempComponent.ColdDamageThreshold = 0;
}

View file

@ -15,6 +15,7 @@ using Content.Server.Weapons.Ranged.Systems;
using Content.Shared.Alert;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.DoAfter;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Inventory;

View file

@ -1,3 +1,4 @@
using System.Linq;
using Content.Shared._Sunrise.Flyswatter;
using Content.Shared.Body.Components;
using Content.Shared.Weapons.Melee;
@ -23,7 +24,12 @@ public sealed class FlyswatterSystem : EntitySystem
if (flyswatter.InsectDamageMultiplier <= 1f)
return;
if (component.BloodReagent != flyswatter.InsectBloodReagent)
// BloodstreamComponent doesn't have a single BloodReagent field.
// Inspect the bloodstream's reference solution contents for the reagent
// prototype ID configured on the flyswatter. This avoids calling methods
// on the Solution instance which may be restricted by component access.
var contents = component.BloodReferenceSolution?.Contents;
if (contents == null || !contents.Any(q => q.Reagent.Prototype == flyswatter.InsectBloodReagent))
return;
// 0 смысла если не бьет

View file

@ -1,5 +1,7 @@
using Content.Server._Sunrise.Heartbeat.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Mobs;
namespace Content.Server._Sunrise.Heartbeat.Systems;

View file

@ -1,6 +1,7 @@
using Content.Server._Sunrise.Heartbeat.Components;
using Content.Shared._Sunrise.Heartbeat;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.GameTicking;
using Content.Shared.Mobs;
using Robust.Server.Audio;

View file

@ -17,6 +17,7 @@ using Robust.Shared.Timing;
using Content.Shared._Sunrise.Mech;
using Content.Shared.Coordinates;
using Content.Shared.Emp;
using Content.Shared.Damage.Systems;
namespace Content.Server._Sunrise.Mech;
@ -86,7 +87,7 @@ public sealed partial class SunriseMechSystem : EntitySystem
ent.Comp.NextPulseTime = curTime + ent.Comp.CooldownTime;
_damageable.TryChangeDamage(ent, ent.Comp.EmpDamage);
_damageable.TryChangeDamage(ent.Owner, ent.Comp.EmpDamage);
EnsureComp<MechOnEMPPulseComponent>(ent);
}

View file

@ -5,6 +5,7 @@ using Content.Shared.Alert;
using Content.Shared.CCVar;
using Content.Shared.Chat;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;

View file

@ -1,6 +1,7 @@
using Content.Server._Sunrise.NoEmotions;
using Content.Server.Chat.Systems;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;

View file

@ -1,4 +1,5 @@
using Content.Server.Maps;
using Content.Shared.Maps;
using Content.Shared.Parallax.Biomes;
using Content.Shared.Whitelist;
using Robust.Shared.Map;

View file

@ -7,6 +7,7 @@ using Content.Server.Shuttles.Systems;
using Content.Shared._Sunrise.Shuttles;
using Content.Shared._Sunrise.SunriseCCVars;
using Content.Shared.Light.Components;
using Content.Shared.Maps;
using Content.Shared.Salvage;
using Content.Shared.Shuttles.Components;
using Robust.Server.GameObjects;

View file

@ -16,6 +16,7 @@ using Content.Shared.Body.Components;
using Content.Shared.DoAfter;
using Content.Shared.Movement.Systems;
using Content.Shared.Zombies;
using Content.Shared.Damage.Systems;
namespace Content.Server._Sunrise.Smile;
@ -105,7 +106,7 @@ public sealed class SmileSlimeSystem : EntitySystem
_entMan.SpawnEntity("EffectHearts", targetXform.Coordinates);
_audio.PlayPvs(comp.SoundSpecifier, targetXform.Coordinates);
_damageableSystem.TryChangeDamage(args.Target, comp.DamageSpecifier, true, false);
_damageableSystem.TryChangeDamage(args.Target.Value, comp.DamageSpecifier, true, false);
args.Handled = true;
}

View file

@ -4,20 +4,20 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy
namespace Content.Server._Sunrise.SponsorLoadout;
[Prototype("sponsorLoadout")]
public sealed class SponsorLoadoutPrototype : IPrototype
[Prototype]
public sealed partial class SponsorLoadoutPrototype : IPrototype
{
[IdDataField] public string ID { get; } = default!;
[IdDataField] public string ID { get; private set; } = default!;
[DataField(required: true)]
public ProtoId<StartingGearPrototype> Equipment;
[DataField("whitelistJobs", customTypeSerializer: typeof(PrototypeIdListSerializer<JobPrototype>))]
public List<string>? WhitelistJobs { get; }
public List<string>? WhitelistJobs { get; private set; }
[DataField("blacklistJobs", customTypeSerializer: typeof(PrototypeIdListSerializer<JobPrototype>))]
public List<string>? BlacklistJobs { get; }
public List<string>? BlacklistJobs { get; private set; }
[DataField("speciesRestriction")]
public List<string>? SpeciesRestrictions { get; }
public List<string>? SpeciesRestrictions { get; private set; }
}

View file

@ -1,4 +1,5 @@
using Content.Server.Maps;
using Content.Shared.Maps;
using Content.Shared.Whitelist;
using Robust.Shared.Map;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;

View file

@ -3,6 +3,7 @@ using Content.Server.GameTicking;
using Content.Server.Maps;
using Content.Server.Shuttles.Systems;
using Content.Shared._Sunrise.AlwaysPoweredMap;
using Content.Shared.Maps;
using Robust.Server.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;

View file

@ -4,11 +4,11 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy
namespace Content.Server._Sunrise.StationGoal
{
[Serializable, Prototype("stationGoal")]
public sealed class StationGoalPrototype : IPrototype
[Prototype]
public sealed partial class StationGoalPrototype : IPrototype
{
[IdDataField]
public string ID { get; } = default!;
public string ID { get; private set; } = default!;
[DataField("text")]
public string Text { get; set; } = string.Empty;

Some files were not shown because too many files have changed in this diff Show more