Ling update (#183)

* - add: Augmented Eyesight.

* - add: Dissonant Shriek.

* - tweak: Nuke use delays.

* - tweak: Tweak chemical regeneration and chemical costs.

* - add: Add chitinous helmet.

* - fix: Fix chem regeneration while dead.

* - tweak: Faster fleshmend.

* - add: Void Adaptation.

* - tweak: No lesser form delay.

* - tweak: Lesser form tweaks.

* - tweak: Stasis doafter is hidden now.

* - add: Refund after absorbing.

* - tweak: Some tweaks.
This commit is contained in:
Aviu00
2024-03-14 01:19:30 +09:00
committed by GitHub
parent 83c3df1593
commit c05a1d09c2
33 changed files with 529 additions and 130 deletions

View File

@@ -31,19 +31,32 @@ namespace Content.Client._White.Overlays
var handle = args.WorldHandle;
if (!_entityManager.TryGetComponent<NightVisionComponent>(_playerManager.LocalSession?.AttachedEntity,
out var component))
Color? color = null;
if (_entityManager.TryGetComponent<NightVisionComponent>(_playerManager.LocalSession?.AttachedEntity,
out var component) && component.IsActive)
{
return;
_shader.SetParameter("tint", component.Tint);
_shader.SetParameter("luminance_threshold", component.Strength);
_shader.SetParameter("noise_amount", component.Noise);
color = component.Color;
}
else if (_entityManager.TryGetComponent<TemporaryNightVisionComponent>(
_playerManager.LocalSession?.AttachedEntity, out var tempNvComp))
{
_shader.SetParameter("tint", tempNvComp.Tint);
_shader.SetParameter("luminance_threshold", tempNvComp.Strength);
_shader.SetParameter("noise_amount", tempNvComp.Noise);
color = tempNvComp.Color;
}
if (color == null)
return;
_shader.SetParameter("SCREEN_TEXTURE", ScreenTexture);
_shader.SetParameter("tint", component.Tint);
_shader.SetParameter("luminance_threshold", component.Strength);
_shader.SetParameter("noise_amount", component.Noise);
handle.UseShader(_shader);
handle.DrawRect(args.WorldBounds, component.Color);
handle.DrawRect(args.WorldBounds, color.Value);
handle.UseShader(null);
}
}

View File

@@ -23,23 +23,56 @@ public sealed class NightVisionSystem : SharedNightVisionSystem
SubscribeLocalEvent<NightVisionComponent, PlayerDetachedEvent>(OnPlayerDetached);
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRestart);
SubscribeLocalEvent<TemporaryNightVisionComponent, ComponentInit>(OnTempInit);
SubscribeLocalEvent<TemporaryNightVisionComponent, ComponentRemove>(OnTempRemove);
SubscribeLocalEvent<TemporaryNightVisionComponent, PlayerAttachedEvent>(OnTempPlayerAttached);
SubscribeLocalEvent<TemporaryNightVisionComponent, PlayerDetachedEvent>(OnTempPlayerDetached);
_overlay = new NightVisionOverlay();
}
private void OnTempPlayerAttached(Entity<TemporaryNightVisionComponent> ent, ref PlayerAttachedEvent args)
{
UpdateNightVision(args.Player, true);
}
private void OnTempPlayerDetached(Entity<TemporaryNightVisionComponent> ent, ref PlayerDetachedEvent args)
{
UpdateNightVision(args.Player, false);
}
private void OnTempRemove(Entity<TemporaryNightVisionComponent> ent, ref ComponentRemove args)
{
if (TryComp(ent, out NightVisionComponent? nightVision) && nightVision.IsActive)
return;
UpdateNightVision(ent, false);
}
private void OnTempInit(Entity<TemporaryNightVisionComponent> ent, ref ComponentInit args)
{
UpdateNightVision(ent, true);
}
private void OnPlayerAttached(EntityUid uid, NightVisionComponent component, PlayerAttachedEvent args)
{
if (_player.LocalSession != args.Player)
if (!component.IsActive && HasComp<TemporaryNightVisionComponent>(args.Entity))
return;
UpdateNightVision(component.IsActive);
UpdateNightVision(args.Player, component.IsActive);
}
private void OnPlayerDetached(EntityUid uid, NightVisionComponent component, PlayerDetachedEvent args)
{
if (_player.LocalSession != args.Player)
UpdateNightVision(args.Player, false);
}
private void UpdateNightVision(ICommonSession player, bool active)
{
if (_player.LocalSession != player)
return;
UpdateNightVision(false);
UpdateNightVision(active);
}
protected override void UpdateNightVision(EntityUid uid, bool active)

View File

@@ -9,6 +9,7 @@ using Content.Shared.FixedPoint;
using Content.Shared.Inventory;
using Content.Shared.Inventory.Events;
using Content.Shared._White.Mood;
using Content.Shared.Changeling;
using Robust.Shared.Containers;
namespace Content.Server.Atmos.EntitySystems
@@ -234,6 +235,12 @@ namespace Content.Server.Atmos.EntitySystems
if (pressure > Atmospherics.WarningLowPressure)
goto default;
if (TryComp(uid, out VoidAdaptationComponent? voidAdaptation)) // WD
{
voidAdaptation.ChemMultiplier = 0.75f;
goto default;
}
// Deal damage and ignore resistances. Resistance to pressure damage should be done via pressure protection gear.
_damageableSystem.TryChangeDamage(uid, barotrauma.Damage * Atmospherics.LowPressureDamage, true, false);

View File

@@ -22,7 +22,8 @@ using Content.Shared.Mobs.Components; // WD
using Content.Shared.Mobs.Systems;
using Content.Shared.Popups; // WD
using Content.Shared._White.CPR.Events;
using Content.Shared._White.Mood; // WD
using Content.Shared._White.Mood;
using Content.Shared.Changeling; // WD
using JetBrains.Annotations;
using Robust.Server.Audio; // WD
using Robust.Shared.Audio; // WD
@@ -97,6 +98,14 @@ public sealed class RespiratorSystem : EntitySystem
if (respirator.Saturation < respirator.SuffocationThreshold)
{
if (TryComp(uid, out VoidAdaptationComponent? voidAdaptation))
{
voidAdaptation.ChemMultiplier = 0.75f;
StopSuffocation(uid, respirator);
respirator.SuffocationCycles = 0;
continue;
}
if (_gameTiming.CurTime >= respirator.LastGaspPopupTime + respirator.GaspPopupCooldown)
{
respirator.LastGaspPopupTime = _gameTiming.CurTime;

View File

@@ -40,7 +40,7 @@ public sealed class ChangelingRuleSystem : GameRuleSystem<ChangelingRuleComponen
private const float ChangelingStartDelay = 3f * 60;
private const float ChangelingStartDelayVariance = 3f * 60;
private const int ChangelingMinPlayers = 10;
private const int ChangelingMinPlayers = 15;
private const int ChangelingMaxDifficulty = 5;
private const int ChangelingMaxPicks = 20;

View File

@@ -6,6 +6,8 @@ using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Server.Cuffs;
using Content.Server.DoAfter;
using Content.Server.Emp;
using Content.Server.Flash.Components;
using Content.Server.Forensics;
using Content.Server.GameTicking.Rules;
using Content.Server.Humanoid;
@@ -19,6 +21,7 @@ using Content.Server.Store.Components;
using Content.Server.Temperature.Components;
using Content.Server.Temperature.Systems;
using Content.Shared._White.Chaplain;
using Content.Shared._White.Overlays;
using Content.Shared.Actions;
using Content.Shared.Changeling;
using Content.Shared.Chemistry.EntitySystems;
@@ -42,6 +45,7 @@ using Content.Shared.Pulling.Components;
using Content.Shared.Standing;
using Content.Shared.StatusEffect;
using Content.Shared.Tag;
using Robust.Server.Containers;
using Robust.Server.GameObjects;
using Robust.Shared.GameObjects.Components.Localization;
using Robust.Shared.Player;
@@ -78,6 +82,9 @@ public sealed partial class ChangelingSystem
[Dependency] private readonly CultRuleSystem _cult = default!;
[Dependency] private readonly NpcFactionSystem _faction = default!;
[Dependency] private readonly TagSystem _tag = default!;
[Dependency] private readonly EmpSystem _empSystem = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly ContainerSystem _container = default!;
private void InitializeAbilities()
{
@@ -97,6 +104,8 @@ public sealed partial class ChangelingSystem
SubscribeLocalEvent<ChangelingComponent, AdrenalineSacsActionEvent>(OnAdrenalineSacs);
SubscribeLocalEvent<ChangelingComponent, FleshmendActionEvent>(OnFleshMend);
SubscribeLocalEvent<ChangelingComponent, BiodegradeActionEvent>(OnBiodegrade);
SubscribeLocalEvent<ChangelingComponent, AugmentedEyesightActionEvent>(OnEyesight);
SubscribeLocalEvent<ChangelingComponent, DissonantShriekActionEvent>(OnDissonantShriek);
SubscribeLocalEvent<ChangelingComponent, ArmbladeActionEvent>(OnArmBlade);
SubscribeLocalEvent<ChangelingComponent, OrganicShieldActionEvent>(OnShield);
@@ -109,6 +118,9 @@ public sealed partial class ChangelingSystem
SubscribeLocalEvent<ChangelingComponent, LesserFormDoAfterEvent>(OnLesserFormDoAfter);
SubscribeLocalEvent<ChangelingComponent, ListViewItemSelectedMessage>(OnTransformUiMessage);
SubscribeLocalEvent<ChangelingComponent, AugmentedEyesightPurchasedEvent>(OnEyesightPurchased);
SubscribeLocalEvent<ChangelingComponent, VoidAdaptationPurchasedEvent>(OnVoidAdaptationPurchased);
}
#region Data
@@ -259,7 +271,8 @@ public sealed partial class ChangelingSystem
new RegenerateDoAfterEvent(), args.Performer,
args.Performer, args.Performer)
{
RequireCanInteract = false
RequireCanInteract = false,
Hidden = true
});
component.IsRegenerating = true;
@@ -267,7 +280,7 @@ public sealed partial class ChangelingSystem
private void OnLesserForm(EntityUid uid, ChangelingComponent component, LesserFormActionEvent args)
{
if (_mobStateSystem.IsDead(uid) || component.IsRegenerating)
if (!_mobStateSystem.IsAlive(uid))
{
_popup.PopupEntity(Loc.GetString("changeling-popup-cant-perform"), uid, uid);
return;
@@ -282,7 +295,8 @@ public sealed partial class ChangelingSystem
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.Performer, component.LesserFormDelay,
new LesserFormDoAfterEvent(), args.Performer, args.Performer)
{
BreakOnUserMove = true
BreakOnUserMove = true,
RequireCanInteract = false
});
}
@@ -490,7 +504,7 @@ public sealed partial class ChangelingSystem
if (!TakeChemicals(uid, component, 20))
return;
_solutionContainer.TryAddReagent(injectable.Value, "Omnizine", 25);
_solutionContainer.TryAddReagent(injectable.Value, "Ichor", 10);
if (TryComp(uid, out BloodstreamComponent? bloodstream))
{
_blood.TryModifyBleedAmount(uid, -bloodstream.BleedAmount, bloodstream);
@@ -501,7 +515,7 @@ public sealed partial class ChangelingSystem
private void OnBiodegrade(EntityUid uid, ChangelingComponent component, BiodegradeActionEvent args)
{
if (_mobStateSystem.IsDead(uid))
if (!_mobStateSystem.IsAlive(uid))
return;
if (!TryComp(uid, out CuffableComponent? cuffs) || cuffs.Container.ContainedEntities.Count < 1)
@@ -512,7 +526,7 @@ public sealed partial class ChangelingSystem
var lastAddedCuffs = cuffs.LastAddedCuffs;
_cuffable.Uncuff(uid, lastAddedCuffs, lastAddedCuffs);
_cuffable.Uncuff(uid, null, lastAddedCuffs);
Del(lastAddedCuffs);
@@ -523,14 +537,14 @@ public sealed partial class ChangelingSystem
private void OnArmBlade(EntityUid uid, ChangelingComponent component, ArmbladeActionEvent args)
{
SpawnOrDeleteItem(uid, "ArmBlade");
SpawnOrDeleteItem(uid, component, "ArmBlade", 20);
args.Handled = true;
}
private void OnShield(EntityUid uid, ChangelingComponent component, OrganicShieldActionEvent args)
{
SpawnOrDeleteItem(uid, "OrganicShield");
SpawnOrDeleteItem(uid, component, "OrganicShield", 20);
args.Handled = true;
}
@@ -538,43 +552,83 @@ public sealed partial class ChangelingSystem
private void OnArmor(EntityUid uid, ChangelingComponent component, ChitinousArmorActionEvent args)
{
const string outerName = "outerClothing";
const string protoName = "ClothingOuterChangeling";
const string headName = "head";
const string armorName = "ClothingOuterChangeling";
const string helmetName = "ClothingHeadHelmetLing";
if (!_inventorySystem.TryGetSlotEntity(uid, outerName, out var outerEnt))
_inventorySystem.TryUnequip(uid, outerName, out var outer, true, true);
_inventorySystem.TryUnequip(uid, headName, out var helmet, true, true);
if (TryComp(outer, out MetaDataComponent? metaData) && metaData.EntityPrototype is {ID: armorName})
{
_inventorySystem.SpawnItemInSlot(uid, outerName, protoName, silent: true);
args.Handled = true;
return;
}
if (!TryComp<MetaDataComponent>(outerEnt, out var meta))
if (!TakeChemicals(uid, component, 20))
{
_inventorySystem.SpawnItemInSlot(uid, outerName, protoName, silent: true);
if (outer != null)
_inventorySystem.TryEquip(uid, outer.Value, outerName, true, true);
if (helmet != null)
_inventorySystem.TryEquip(uid, helmet.Value, headName, true, true);
return;
}
if (meta.EntityPrototype == null)
{
_inventorySystem.SpawnItemInSlot(uid, outerName, protoName, silent: true);
return;
}
if (meta.EntityPrototype.ID == protoName)
{
_inventorySystem.TryUnequip(uid, outerName, out var removedItem, force: true);
QueueDel(removedItem);
return;
}
_inventorySystem.TryUnequip(uid, outerName, out _);
_inventorySystem.SpawnItemInSlot(uid, outerName, protoName, silent: true);
_inventorySystem.SpawnItemInSlot(uid, outerName, armorName, true, true);
_inventorySystem.SpawnItemInSlot(uid, headName, helmetName, true, true);
args.Handled = true;
}
private void OnTentacleArm(EntityUid uid, ChangelingComponent component, TentacleArmActionEvent args)
{
SpawnOrDeleteItem(uid, "TentacleArmGun");
SpawnOrDeleteItem(uid, component, "TentacleArmGun", 10);
args.Handled = true;
}
private void OnEyesightPurchased(Entity<ChangelingComponent> ent, ref AugmentedEyesightPurchasedEvent args)
{
EnsureComp<FlashImmunityComponent>(ent);
EnsureComp<EyeProtectionComponent>(ent);
}
private void OnVoidAdaptationPurchased(Entity<ChangelingComponent> ent, ref VoidAdaptationPurchasedEvent args)
{
EnsureComp<VoidAdaptationComponent>(ent);
}
private void OnEyesight(Entity<ChangelingComponent> ent, ref AugmentedEyesightActionEvent args)
{
if (!_mobStateSystem.IsAlive(ent))
return;
args.Handled = true;
if (HasComp<TemporaryNightVisionComponent>(ent))
{
RemComp<TemporaryNightVisionComponent>(ent);
EnsureComp<FlashImmunityComponent>(ent);
EnsureComp<EyeProtectionComponent>(ent);
return;
}
EnsureComp<TemporaryNightVisionComponent>(ent);
RemComp<FlashImmunityComponent>(ent);
RemComp<EyeProtectionComponent>(ent);
}
private void OnDissonantShriek(Entity<ChangelingComponent> ent, ref DissonantShriekActionEvent args)
{
if (!_mobStateSystem.IsAlive(ent))
return;
if (!TakeChemicals(ent, ent.Comp, 20))
return;
_empSystem.EmpPulse(_transform.GetMapCoordinates(ent), 5, 100000, 10f);
args.Handled = true;
}
@@ -612,6 +666,20 @@ public sealed partial class ChangelingSystem
component.AbsorbedCount++;
_chemicalsSystem.AddChemicals(uid, component, 50);
if (_container.TryGetContainer(uid, ImplanterComponent.ImplantSlotId, out var implantContainer))
{
foreach (var implant in implantContainer.ContainedEntities)
{
if (!TryComp<StoreComponent>(implant, out var store) || store.Preset != "StorePresetChangeling")
continue;
store.Refunds = true;
store.RefundAllowed = true;
}
}
if (TryComp(uid, out SharedPullerComponent? puller) && puller.Pulling is { } pulled &&
TryComp(pulled, out SharedPullableComponent? pullable))
{
@@ -653,6 +721,7 @@ public sealed partial class ChangelingSystem
{
if (args.Handled || args.Cancelled || args.Target == null)
{
component.IsRegenerating = false;
return;
}
@@ -664,7 +733,10 @@ public sealed partial class ChangelingSystem
}
if (!TakeChemicals(uid, component, 15))
{
component.IsRegenerating = false;
return;
}
_rejuvenate.PerformRejuvenate(args.Target.Value);
@@ -682,14 +754,14 @@ public sealed partial class ChangelingSystem
if (args.Handled || args.Cancelled)
return;
if (!TakeChemicals(uid, component, 5))
return;
var polymorphEntity = _polymorph.PolymorphEntity(args.User, "MonkeyChangeling");
if (polymorphEntity == null)
return;
if (!TakeChemicals(uid, component, 5))
return;
var toAdd = new ChangelingComponent
{
HiveName = component.HiveName,
@@ -701,6 +773,8 @@ public sealed partial class ChangelingSystem
EntityManager.AddComponent(polymorphEntity.Value, toAdd);
TransferComponents(uid, polymorphEntity.Value);
_implantSystem.TransferImplants(uid, polymorphEntity.Value);
_actionContainerSystem.TransferAllActionsFiltered(uid, polymorphEntity.Value, polymorphEntity.Value);
_action.GrantContainedActions(polymorphEntity.Value, polymorphEntity.Value);
@@ -830,12 +904,6 @@ public sealed partial class ChangelingSystem
_identity.QueueIdentityUpdate(polymorphEntity.Value);
if (HasComp<BibleUserComponent>(target))
EnsureComp<BibleUserComponent>(polymorphEntity.Value);
if (HasComp<HolyComponent>(target))
EnsureComp<HolyComponent>(polymorphEntity.Value);
if (TryComp(target, out ChangelingComponent? lingComp))
{
var toAdd = new ChangelingComponent
@@ -850,18 +918,7 @@ public sealed partial class ChangelingSystem
_chemicalsSystem.UpdateAlert(polymorphEntity.Value, toAdd);
}
if (TryComp(target, out NpcFactionMemberComponent? factionMember))
{
_faction.ClearFactions(polymorphEntity.Value);
foreach (var faction in factionMember.Factions)
{
_faction.AddFaction(polymorphEntity.Value, faction);
}
}
_nukeOps.TransferRole(target, polymorphEntity.Value);
_cult.TransferRole(target, polymorphEntity.Value);
TransferComponents(target, polymorphEntity.Value);
_implantSystem.TransferImplants(target, polymorphEntity.Value);
_actionContainerSystem.TransferAllActionsFiltered(target, polymorphEntity.Value, polymorphEntity.Value);
@@ -870,6 +927,50 @@ public sealed partial class ChangelingSystem
return polymorphEntity;
}
private void TransferComponents(EntityUid from, EntityUid to)
{
if (HasComp<BibleUserComponent>(from))
EnsureComp<BibleUserComponent>(to);
if (HasComp<HolyComponent>(from))
EnsureComp<HolyComponent>(to);
if (HasComp<FlashImmunityComponent>(from))
EnsureComp<FlashImmunityComponent>(to);
if (HasComp<EyeProtectionComponent>(from))
EnsureComp<EyeProtectionComponent>(to);
if (HasComp<VoidAdaptationComponent>(from))
EnsureComp<VoidAdaptationComponent>(to);
if (TryComp(from, out TemporaryNightVisionComponent? nvComp))
{
var toAdd = new TemporaryNightVisionComponent
{
Color = nvComp.Color,
Tint = nvComp.Tint,
Strength = nvComp.Strength,
Noise = nvComp.Noise
};
EntityManager.AddComponent(to, toAdd);
}
if (TryComp(from, out NpcFactionMemberComponent? factionMember))
{
_faction.ClearFactions(to);
foreach (var faction in factionMember.Factions)
{
_faction.AddFaction(to, faction);
}
}
_nukeOps.TransferRole(from, to);
_cult.TransferRole(from, to);
}
private void TransferDna(EntityUid target, string dna)
{
if (!TryComp<DnaComponent>(target, out var dnaComponent))
@@ -932,7 +1033,7 @@ public sealed partial class ChangelingSystem
Dirty(target, targetHumanoid);
}
private void SpawnOrDeleteItem(EntityUid target, string prototypeName)
private void SpawnOrDeleteItem(EntityUid target, ChangelingComponent component, string prototypeName, int chemicals)
{
foreach (var eHand in _handsSystem.EnumerateHands(target))
{
@@ -952,6 +1053,9 @@ public sealed partial class ChangelingSystem
return;
}
if (!TakeChemicals(target, component, chemicals))
return;
var item = Spawn(prototypeName, Transform(target).Coordinates);
if (!_handsSystem.TryPickup(target, item, hand, animate: false))

View File

@@ -1,9 +1,10 @@
using Content.Server.Store.Components;
using Content.Server.Store.Systems;
using Content.Server.Flash.Components;
using Content.Server.Store.Components;
using Content.Shared._White.Overlays;
using Content.Shared.Changeling;
using Content.Shared.Eye.Blinding.Components;
using Content.Shared.Implants.Components;
using Robust.Server.GameStates;
using Robust.Server.Placement;
using Content.Shared.Inventory;
namespace Content.Server.Changeling;
@@ -11,7 +12,35 @@ public sealed partial class ChangelingSystem
{
private void InitializeShop()
{
SubscribeLocalEvent<SubdermalImplantComponent, ChangelingShopActionEvent>(OnShop);
SubscribeLocalEvent<SubdermalImplantComponent, ChangelingShopActionEvent>(OnShop);
SubscribeLocalEvent<ChangelingComponent, ChangelingRefundEvent>(OnChangelingRefund);
SubscribeLocalEvent<DeleteOnChangelingRefundComponent, InventoryRelayedEvent<ChangelingRefundEvent>>(OnRefund);
}
private void OnRefund(Entity<DeleteOnChangelingRefundComponent> ent,
ref InventoryRelayedEvent<ChangelingRefundEvent> args)
{
QueueDel(ent);
}
private void OnChangelingRefund(Entity<ChangelingComponent> ent, ref ChangelingRefundEvent args)
{
RemComp<EyeProtectionComponent>(ent);
RemComp<FlashImmunityComponent>(ent);
RemComp<TemporaryNightVisionComponent>(ent);
RemComp<VoidAdaptationComponent>(ent);
foreach (var hand in _handsSystem.EnumerateHands(ent))
{
if (hand.HeldEntity != null && HasComp<DeleteOnChangelingRefundComponent>(hand.HeldEntity.Value))
QueueDel(hand.HeldEntity.Value);
}
if (!TryComp(args.Store, out StoreComponent? storeComponent))
return;
storeComponent.Refunds = false;
_storeSystem.DisableRefund(args.Store, storeComponent);
}
private void OnShop(EntityUid uid, SubdermalImplantComponent component, ChangelingShopActionEvent args)

View File

@@ -5,6 +5,7 @@ using Content.Server.PDA.Ringer;
using Content.Server.Stack;
using Content.Server.Store.Components;
using Content.Shared.Actions;
using Content.Shared.Changeling;
using Content.Shared.Database;
using Content.Shared.FixedPoint;
using Content.Shared.Hands.EntitySystems;
@@ -364,6 +365,7 @@ public sealed partial class StoreSystem
// Reset store back to its original state
RefreshAllListings(component);
component.BalanceSpent = new();
RaiseLocalEvent(buyer, new ChangelingRefundEvent {Store = uid}); // WD
UpdateUserInterface(buyer, uid, component);
}

View File

@@ -6,6 +6,7 @@ using Content.Server.Body.Components;
using Content.Server.Temperature.Components;
using Content.Shared.Alert;
using Content.Shared.Atmos;
using Content.Shared.Changeling;
using Content.Shared.Damage;
using Content.Shared.Database;
using Content.Shared.Inventory;
@@ -279,6 +280,19 @@ public sealed class TemperatureSystem : EntitySystem
}
else if (temperature.CurrentTemperature <= coldDamageThreshold)
{
if (TryComp(uid, out VoidAdaptationComponent? voidAdaptation)) // WD
{
if (temperature.TakingDamage)
{
_adminLogger.Add(LogType.Temperature,
$"{ToPrettyString(uid):entity} stopped taking temperature damage");
temperature.TakingDamage = false;
}
voidAdaptation.ChemMultiplier = 0.75f;
return;
}
if (!temperature.TakingDamage)
{
_adminLogger.Add(LogType.Temperature, $"{ToPrettyString(uid):entity} started taking low temperature damage");

View File

@@ -1,5 +1,6 @@
using Content.Server.Temperature.Components;
using Content.Server.Temperature.Systems;
using Content.Shared.Changeling;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
@@ -20,7 +21,9 @@ public sealed class LowTemperatureSlowdownSystem : EntitySystem
private void OnMoveSpeedRefresh(EntityUid uid, TemperatureComponent component,
RefreshMovementSpeedModifiersEvent args)
{
var modifier = !component.Slowdown ? 1f : GetSpeedModifier(component.CurrentTemperature);
var modifier = HasComp<VoidAdaptationComponent>(uid) || !component.Slowdown
? 1f
: GetSpeedModifier(component.CurrentTemperature);
args.ModifySpeed(modifier, modifier);
}

View File

@@ -1,4 +1,4 @@
using Content.Shared.Humanoid;
using Content.Shared.Humanoid;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
@@ -9,7 +9,7 @@ namespace Content.Shared.Changeling;
public sealed partial class ChangelingComponent : Component
{
[DataField("chemRegenRate")]
public int ChemicalRegenRate = 2;
public int ChemicalRegenRate = 4;
[DataField("chemicalCap")]
public int ChemicalCapacity = 75;
@@ -24,7 +24,7 @@ public sealed partial class ChangelingComponent : Component
public float Accumulator;
[ViewVariables(VVAccess.ReadOnly)]
public float UpdateDelay = 6f;
public float UpdateDelay = 4f;
[ViewVariables(VVAccess.ReadOnly)]
public bool IsRegenerating;
@@ -48,13 +48,13 @@ public sealed partial class ChangelingComponent : Component
public float AbsorbDnaDelay = 10f;
[ViewVariables(VVAccess.ReadWrite), DataField("TransformDelay")]
public float TransformDelay = 2f;
public float TransformDelay;
[ViewVariables(VVAccess.ReadWrite), DataField("RegenerateDelay")]
public float RegenerateDelay = 60f;
[ViewVariables(VVAccess.ReadWrite), DataField("LesserFormDelay")]
public float LesserFormDelay = 5f;
public float LesserFormDelay;
public bool IsInited;
}

View File

@@ -1,4 +1,5 @@
using Content.Shared.Alert;
using Content.Shared.Alert;
using Content.Shared.Inventory;
using Content.Shared.Mobs.Systems;
using Robust.Shared.Network;
@@ -10,24 +11,38 @@ public sealed class ChemicalsSystem : EntitySystem
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
[Dependency] private readonly INetManager _net = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ClothingModifyChemicalRegenComponent, InventoryRelayedEvent<ChemRegenModifyEvent>>(
OnChemRegenModify);
SubscribeLocalEvent<VoidAdaptationComponent, ChemRegenModifyEvent>(OnVoidAdaptationChemRegenModify);
}
private void OnVoidAdaptationChemRegenModify(Entity<VoidAdaptationComponent> ent, ref ChemRegenModifyEvent args)
{
args.Multiplier *= ent.Comp.ChemMultiplier;
ent.Comp.ChemMultiplier = 1f;
}
private void OnChemRegenModify(Entity<ClothingModifyChemicalRegenComponent> ent,
ref InventoryRelayedEvent<ChemRegenModifyEvent> args)
{
args.Args.Multiplier *= ent.Comp.Multiplier;
}
public bool AddChemicals(EntityUid uid, ChangelingComponent component, int quantity)
{
var capacity = component.ChemicalCapacity;
if (_mobStateSystem.IsDead(uid))
capacity /= 2;
if (component.ChemicalsBalance >= capacity)
return false;
var toAdd = quantity;
component.ChemicalsBalance = Math.Min(component.ChemicalsBalance + quantity, capacity);
if (component.ChemicalsBalance == component.ChemicalCapacity)
return false;
if (component.ChemicalsBalance + toAdd > component.ChemicalCapacity)
{
var overflow = component.ChemicalsBalance + toAdd - component.ChemicalCapacity;
toAdd -= overflow;
component.ChemicalsBalance += toAdd;
}
component.ChemicalsBalance += toAdd;
Dirty(uid, component);
UpdateAlert(uid, component);
@@ -69,11 +84,11 @@ public sealed class ChemicalsSystem : EntitySystem
if(component.Accumulator < component.UpdateDelay)
continue;
if (component.IsRegenerating)
continue;
component.Accumulator = 0;
AddChemicals(uid, component, component.ChemicalRegenRate);
var ev = new ChemRegenModifyEvent();
RaiseLocalEvent(uid, ev);
var chemicals = (int) MathF.Round(component.ChemicalRegenRate * ev.Multiplier);
AddChemicals(uid, component, chemicals);
}
}

View File

@@ -0,0 +1,8 @@
namespace Content.Shared.Changeling;
[RegisterComponent]
public sealed partial class ClothingModifyChemicalRegenComponent : Component
{
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float Multiplier = 0.75f;
}

View File

@@ -0,0 +1,6 @@
namespace Content.Shared.Changeling;
[RegisterComponent]
public sealed partial class DeleteOnChangelingRefundComponent : Component
{
}

View File

@@ -1,5 +1,6 @@
using Content.Shared.Actions;
using Content.Shared.Actions;
using Content.Shared.DoAfter;
using Content.Shared.Inventory;
using Robust.Shared.Serialization;
namespace Content.Shared.Changeling;
@@ -97,3 +98,34 @@ public sealed partial class BiodegradeActionEvent : InstantActionEvent
{
}
public sealed partial class AugmentedEyesightActionEvent : InstantActionEvent
{
}
[Serializable, NetSerializable]
public sealed class AugmentedEyesightPurchasedEvent : EntityEventArgs
{
}
public sealed partial class DissonantShriekActionEvent : InstantActionEvent
{
}
[Serializable, NetSerializable]
public sealed class VoidAdaptationPurchasedEvent : EntityEventArgs
{
}
public sealed class ChemRegenModifyEvent : EntityEventArgs, IInventoryRelayEvent
{
public SlotFlags TargetSlots => ~SlotFlags.POCKET;
public float Multiplier = 1f;
}
public sealed class ChangelingRefundEvent : EntityEventArgs, IInventoryRelayEvent
{
public SlotFlags TargetSlots => SlotFlags.All;
public EntityUid Store;
}

View File

@@ -0,0 +1,7 @@
namespace Content.Shared.Changeling;
[RegisterComponent]
public sealed partial class VoidAdaptationComponent : Component
{
public float ChemMultiplier = 1f;
}

View File

@@ -1,4 +1,5 @@
using Content.Shared._White.StaminaProtection;
using Content.Shared.Changeling;
using Content.Shared.Chemistry;
using Content.Shared.Damage;
using Content.Shared.Electrocution;
@@ -29,6 +30,8 @@ public partial class InventorySystem
SubscribeLocalEvent<InventoryComponent, ModifyChangedTemperatureEvent>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, AdjustTemperatureEvent>(RelayInventoryEvent); // WD
SubscribeLocalEvent<InventoryComponent, StaminaDamageModifyEvent>(RelayInventoryEvent); // WD
SubscribeLocalEvent<InventoryComponent, ChemRegenModifyEvent>(RelayInventoryEvent); // WD
SubscribeLocalEvent<InventoryComponent, ChangelingRefundEvent>(RelayInventoryEvent); // WD
SubscribeLocalEvent<InventoryComponent, GetDefaultRadioChannelEvent>(RelayInventoryEvent);
// by-ref events

View File

@@ -132,7 +132,6 @@ public partial class ListingData : IEquatable<ListingData>, ICloneable
Description != listing.Description ||
ProductEntity != listing.ProductEntity ||
ProductAction != listing.ProductAction ||
ProductEvent != listing.ProductEvent ||
RestockTime != listing.RestockTime)
return false;

View File

@@ -23,12 +23,20 @@ public abstract class SharedNightVisionSystem : EntitySystem
private void OnRemove(EntityUid uid, NightVisionComponent component, ComponentRemove args)
{
_actions.RemoveAction(uid, component.ToggleActionEntity);
if (HasComp<TemporaryNightVisionComponent>(uid))
return;
UpdateNightVision(uid, false);
}
private void OnInit(EntityUid uid, NightVisionComponent component, ComponentInit args)
{
_actions.AddAction(uid, ref component.ToggleActionEntity, component.ToggleAction);
if (!component.IsActive && HasComp<TemporaryNightVisionComponent>(uid))
return;
UpdateNightVision(uid, component.IsActive);
}
@@ -41,8 +49,12 @@ public abstract class SharedNightVisionSystem : EntitySystem
component.IsActive = !component.IsActive;
_audio.PlayPredicted(component.ToggleSound, uid, uid);
UpdateNightVision(uid, component.IsActive);
args.Handled = true;
if (!component.IsActive && HasComp<TemporaryNightVisionComponent>(uid))
return;
UpdateNightVision(uid, component.IsActive);
}
}

View File

@@ -0,0 +1,19 @@
using Robust.Shared.GameStates;
namespace Content.Shared._White.Overlays;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class TemporaryNightVisionComponent : Component
{
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public Vector3 Tint = new(0.3f, 0.3f, 0.3f);
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public float Strength = 2f;
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public float Noise = 0.5f;
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public Color Color = Color.FromHex("#FB9898");
}

View File

@@ -1,9 +1,18 @@
changeling-ability-fleshmend = Восстановление тканей
changeling-ability-fleshmend = Восстановление тканей
changeling-ability-fleshmend-desc = Быстро вылечить большую часть повреждений
changeling-ability-biodegrade = Биоразложение
changeling-ability-biodegrade-desc = Растворяет наручники и прочие сдерживающие элементы.
changeling-ability-eyesight = Аугментация зрения
changeling-ability-eyesight-desc = Развивает переключаемое ночное зрение. Когда способность неактивна, защищает вас от флешек и яркого света, например от сварки.
changeling-ability-dissonant-shriek = Диссонирующий вопль
changeling-ability-dissonant-shriek-desc = Испускает заряд ЭМИ, который нарушает работу всего оборудования вокруг.
changeling-ability-void-adaptation = Пустотная адаптация
changeling-ability-void-adaptation-desc = Наделяет пассивной способностью, позволяющей сопротивляться холоду, низкому давлению и потребности в кислороде. При использовании замедляет регенерацию химикатов на 25%.
changeling-ability-adrenaline-sacks = Мешки с адреналином
changeling-ability-adrenaline-sacks-desc = Дает кратковременный прилив адреналина в крови.

View File

@@ -21,7 +21,7 @@
icon: White/Actions/changeling.rsi/absorb.png
event: !type:AbsorbDnaActionEvent
canTargetSelf: false
useDelay: 10
useDelay: 1
- type: LesserFormRestricted
- type: entity
@@ -34,7 +34,7 @@
itemIconStyle: NoItem
icon: White/Actions/changeling.rsi/transform.png
event: !type:TransformActionEvent
useDelay: 30
useDelay: 1
- type: entity
id: ActionChangelingRegenerate
@@ -47,8 +47,7 @@
icon: White/Actions/changeling.rsi/reviving_stasis.png
event: !type:RegenerateActionEvent
checkCanInteract: false
useDelay: 120
- type: LesserFormRestricted
useDelay: 1
- type: entity
id: ActionChangelingLesserForm
@@ -60,7 +59,8 @@
itemIconStyle: NoItem
icon: White/Actions/changeling.rsi/lesser_form.png
event: !type:LesserFormActionEvent
useDelay: 90
useDelay: 1
checkCanInteract: false
- type: LesserFormRestricted
- type: entity
@@ -74,8 +74,7 @@
icon: White/Actions/changeling.rsi/sting_extract.png
event: !type:ExtractionStingActionEvent
canTargetSelf: false
useDelay: 40
- type: LesserFormRestricted
useDelay: 1
- type: entity
id: ActionTransformSting
@@ -88,8 +87,7 @@
icon: White/Actions/changeling.rsi/sting_transform.png
event: !type:TransformStingActionEvent
canTargetSelf: false
useDelay: 120
- type: LesserFormRestricted
useDelay: 1
- type: entity
id: ActionBlindSting
@@ -102,8 +100,7 @@
icon: White/Actions/changeling.rsi/sting_blind.png
event: !type:BlindStingActionEvent
canTargetSelf: false
useDelay: 30
- type: LesserFormRestricted
useDelay: 1
- type: entity
id: ActionMuteSting
@@ -116,8 +113,7 @@
icon: White/Actions/changeling.rsi/sting_mute.png
event: !type:MuteStingActionEvent
canTargetSelf: false
useDelay: 30
- type: LesserFormRestricted
useDelay: 1
- type: entity
id: ActionHallucinationSting
@@ -130,8 +126,7 @@
icon: White/Actions/changeling.rsi/sting_hallucination.png
event: !type:HallucinationStingActionEvent
canTargetSelf: false
useDelay: 30
- type: LesserFormRestricted
useDelay: 1
- type: entity
id: ActionCryoSting
@@ -144,8 +139,7 @@
icon: White/Actions/changeling.rsi/sting_cryo.png
event: !type:CryoStingActionEvent
canTargetSelf: false
useDelay: 30
- type: LesserFormRestricted
useDelay: 1
- type: entity
id: ActionAdrenalineSacs
@@ -157,7 +151,7 @@
itemIconStyle: NoItem
icon: White/Actions/changeling.rsi/adrenaline_sacs.png
event: !type:AdrenalineSacsActionEvent
useDelay: 60
useDelay: 1
- type: LesserFormRestricted
- type: entity
@@ -170,7 +164,7 @@
itemIconStyle: NoItem
icon: White/Actions/changeling.rsi/fleshmend.png
event: !type:FleshmendActionEvent
useDelay: 60
useDelay: 1
- type: LesserFormRestricted
- type: entity
@@ -183,7 +177,7 @@
itemIconStyle: NoItem
icon: White/Actions/changeling.rsi/arm_blade.png
event: !type:ArmbladeActionEvent
useDelay: 10
useDelay: 1
- type: LesserFormRestricted
- type: entity
@@ -196,7 +190,7 @@
itemIconStyle: NoItem
icon: White/Actions/changeling.rsi/shield.png
event: !type:OrganicShieldActionEvent
useDelay: 10
useDelay: 1
- type: LesserFormRestricted
- type: entity
@@ -209,7 +203,7 @@
itemIconStyle: NoItem
icon: White/Actions/changeling.rsi/armor.png
event: !type:ChitinousArmorActionEvent
useDelay: 10
useDelay: 1
- type: LesserFormRestricted
- type: entity
@@ -222,7 +216,7 @@
itemIconStyle: NoItem
icon: White/Actions/changeling.rsi/tentacle_arm.png
event: !type:TentacleArmActionEvent
useDelay: 10
useDelay: 1
- type: LesserFormRestricted
- type: entity
@@ -236,4 +230,30 @@
checkCanInteract: false
icon: White/Actions/changeling.rsi/biodegrade.png
event: !type:BiodegradeActionEvent
useDelay: 120
useDelay: 1
- type: entity
id: ActionAugmentedEyesight
name: changeling-ability-eyesight
description: changeling-ability-eyesight-desc
noSpawn: true
components:
- type: InstantAction
itemIconStyle: NoItem
checkCanInteract: false
icon: White/Actions/changeling.rsi/augmented_eyesight.png
event: !type:AugmentedEyesightActionEvent
- type: entity
id: ActionDissonantShriek
name: changeling-ability-dissonant-shriek
description: changeling-ability-dissonant-shriek-desc
noSpawn: true
components:
- type: InstantAction
itemIconStyle: NoItem
checkCanInteract: false
icon: White/Actions/changeling.rsi/dissonant_shriek.png
event: !type:DissonantShriekActionEvent
useDelay: 1
- type: LesserFormRestricted

View File

@@ -64,6 +64,20 @@
- !type:ListingLimitedStockCondition
stock: 1
- type: listing
id: ChangelingVoidAdaptation
name: changeling-ability-void-adaptation
description: changeling-ability-void-adaptation-desc
icon: { sprite: /Textures/White/Actions/changeling.rsi, state: organic_suit }
productEvent: !type:VoidAdaptationPurchasedEvent
cost:
ChangelingPoint: 2
categories:
- ChangelingAbilities
conditions:
- !type:ListingLimitedStockCondition
stock: 1
# Stings
- type: listing
id: ChangelingExtractionString
@@ -182,3 +196,30 @@
conditions:
- !type:ListingLimitedStockCondition
stock: 1
- type: listing
id: ChangelingAugmentedEyesight
name: changeling-ability-eyesight
description: changeling-ability-eyesight-desc
productAction: ActionAugmentedEyesight
productEvent: !type:AugmentedEyesightPurchasedEvent
cost:
ChangelingPoint: 2
categories:
- ChangelingBoosters
conditions:
- !type:ListingLimitedStockCondition
stock: 1
- type: listing
id: ChangelingDissonantShriek
name: changeling-ability-dissonant-shriek
description: changeling-ability-dissonant-shriek-desc
productAction: ActionDissonantShriek
cost:
ChangelingPoint: 1
categories:
- ChangelingBoosters
conditions:
- !type:ListingLimitedStockCondition
stock: 1

View File

@@ -288,10 +288,13 @@
- type: Armor #admeme item so it should be fine being overpowered while helmets are still intentionally kneecapped.
modifiers:
coefficients:
Blunt: 0.5
Slash: 0.5
Piercing: 0.5
Heat: 0.9
Blunt: 0.8
Slash: 0.8
Piercing: 0.85
Heat: 0.8
- type: Unremoveable
deleteOnDrop: true
- type: DeleteOnChangelingRefund
#ERT HELMETS
#ERT Leader Helmet

View File

@@ -171,8 +171,11 @@
Heat: 0.5
- type: ExplosionResistance
damageCoefficient: 0.9
- type: GroupExamine
- type: Unremoveable
deleteOnDrop: true
- type: ClothingModifyChemicalRegen
- type: DeleteOnChangelingRefund
- type: entity
parent: ClothingOuterArmorHeavy

View File

@@ -143,6 +143,7 @@
Piercing: 1.5
- type: Unremoveable
deleteOnDrop: true
- type: DeleteOnChangelingRefund
- type: Destructible
thresholds:
- trigger:

View File

@@ -298,6 +298,7 @@
volume: -10
- type: Unremoveable
deleteOnDrop: true
- type: DeleteOnChangelingRefund
# Admeme

View File

@@ -28,3 +28,4 @@
- type: Unremoveable
deleteOnDrop: true
- type: ToolForcePowered
- type: DeleteOnChangelingRefund

View File

@@ -137,10 +137,6 @@
color: "#f4692e"
recognizable: true
metabolisms:
Drink:
effects:
- !type:SatiateThirst
factor: 1.5
# Dragon doesn't require airloss healing, so omnizine is still best for humans.
Medicine:
effects:

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

View File

@@ -1,4 +1,4 @@
{
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "By SS14 White Dream",
@@ -22,6 +22,15 @@
{
"name": "biodegrade"
},
{
"name": "augmented_eyesight"
},
{
"name": "dissonant_shriek"
},
{
"name": "organic_suit"
},
{
"name": "fleshmend"
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 B