general bugfixes from commit dc16cad on Goob#1235

This commit is contained in:
Spielern 2025-01-25 21:12:55 -05:00
parent 2e0d4eb492
commit 7ad8b231ad
12 changed files with 163 additions and 23 deletions

View File

@ -9,6 +9,7 @@ using Content.Server.Jobs;
using Content.Server.Materials;
using Content.Server.Popups;
using Content.Server.Power.EntitySystems;
using Content.Shared._EE.Silicon.Components; // Goobstation
using Content.Server.Psionics; // DeltaV
using Content.Server.Traits.Assorted; // DeltaV
using Content.Shared.Atmos;
@ -171,6 +172,9 @@ namespace Content.Server.Cloning
if (!TryComp<HumanoidAppearanceComponent>(bodyToClone, out var humanoid))
return false; // whatever body was to be cloned, was not a humanoid
if (HasComp<SiliconComponent>(bodyToClone))
return false; // Goobstation: Don't clone IPCs.
// Begin Nyano-code: allow paradox anomalies to be cloned.
var pref = humanoid.LastProfileLoaded;

View File

@ -8,4 +8,6 @@ namespace Content.Server.Objectives.Components;
[RegisterComponent, Access(typeof(KillPersonConditionSystem))]
public sealed partial class PickRandomPersonComponent : Component
{
[DataField]
public bool NeedsOrganic; // Goobstation: Only pick non-silicon players.
}

View File

@ -228,8 +228,8 @@ public sealed partial class PowerCellSystem : SharedPowerCellSystem
private void OnCellSlotExamined(EntityUid uid, PowerCellSlotComponent component, ExaminedEvent args)
{
TryGetBatteryFromSlot(uid, out var battery);
OnBatteryExamined(uid, battery, args);
TryGetBatteryFromSlot(uid, out var batteryEnt, out var battery); // Goobstation
OnBatteryExamined(batteryEnt.GetValueOrDefault(uid), battery, args); // Goobstation
}
private void OnBatteryExamined(EntityUid uid, BatteryComponent? component, ExaminedEvent args)

View File

@ -7,6 +7,8 @@ using Content.Shared.Damage;
using Content.Shared.Interaction;
using Content.Shared.Popups;
using Content.Shared.Tools;
using Content.Shared._Shitmed.Targeting;
using Content.Shared.Body.Systems;
using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem;
namespace Content.Server._EE.Silicon.WeldingHealable;
@ -18,6 +20,7 @@ public sealed class WeldingHealableSystem : SharedWeldingHealableSystem
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
[Dependency] private readonly SharedBodySystem _bodySystem = default!;
public override void Initialize()
{
SubscribeLocalEvent<WeldingHealableComponent, InteractUsingEvent>(Repair);
@ -31,7 +34,7 @@ public sealed class WeldingHealableSystem : SharedWeldingHealableSystem
|| !TryComp<WeldingHealingComponent>(args.Used, out var component)
|| damageable.DamageContainerID is null
|| !component.DamageContainers.Contains(damageable.DamageContainerID)
|| !HasDamage(damageable, component)
|| !HasDamage((args.Target.Value, damageable), component, args.User)
|| !TryComp<WelderComponent>(args.Used, out var welder)
|| !TryComp<SolutionContainerManagerComponent>(args.Used, out var solutionContainer)
|| !_solutionContainer.TryGetSolution(((EntityUid) args.Used, solutionContainer), welder.FuelSolutionName, out var solution))
@ -67,7 +70,7 @@ public sealed class WeldingHealableSystem : SharedWeldingHealableSystem
|| !EntityManager.TryGetComponent(args.Target, out DamageableComponent? damageable)
|| damageable.DamageContainerID is null
|| !component.DamageContainers.Contains(damageable.DamageContainerID)
|| !HasDamage(damageable, component)
|| !HasDamage((args.Target, damageable), component, args.User)
|| !_toolSystem.HasQuality(args.Used, component.QualityNeeded)
|| args.User == args.Target && !component.AllowSelfHeal)
return;
@ -88,15 +91,25 @@ public sealed class WeldingHealableSystem : SharedWeldingHealableSystem
});
}
private bool HasDamage(DamageableComponent component, WeldingHealingComponent healable)
private bool HasDamage(Entity<DamageableComponent> damageable, WeldingHealingComponent healable, EntityUid user)
{
if (healable.Damage.DamageDict is null)
return false;
foreach (var type in healable.Damage.DamageDict)
if (component.Damage.DamageDict[type.Key].Value > 0)
if (damageable.Comp.Damage.DamageDict[type.Key].Value > 0)
return true;
// In case the healer is a humanoid entity with targeting, we run the check on the targeted parts.
if (!TryComp(user, out TargetingComponent? targeting))
return false;
var (targetType, targetSymmetry) = _bodySystem.ConvertTargetBodyPart(targeting.Target);
foreach (var part in _bodySystem.GetBodyChildrenOfType(damageable, targetType, symmetry: targetSymmetry))
if (TryComp<DamageableComponent>(part.Id, out var damageablePart))
foreach (var type in healable.Damage.DamageDict)
if (damageablePart.Damage.DamageDict[type.Key].Value > 0)
return true;
return false;
}
}

View File

@ -21,6 +21,16 @@ using Robust.Shared.Network;
using Robust.Shared.Serialization;
using Robust.Shared.Timing;
// Goobstation Change
using Content.Shared.CCVar;
using Content.Shared._Goobstation.CCVar;
using Content.Shared.Weapons.Ranged.Events;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Inventory.VirtualItem;
using Robust.Shared.Configuration;
using Content.Shared.Implants.Components;
namespace Content.Shared.Mech.EntitySystems;
/// <summary>
@ -39,6 +49,12 @@ public abstract class SharedMechSystem : EntitySystem
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!; // Goobstation Change
[Dependency] private readonly SharedVirtualItemSystem _virtualItem = default!; // Goobstation Change
[Dependency] private readonly IConfigurationManager _config = default!; // Goobstation Change
// Goobstation: Local variable for checking if mech guns can be used out of them.
private bool _canUseMechGunOutside;
/// <inheritdoc/>
public override void Initialize()
@ -55,6 +71,14 @@ public abstract class SharedMechSystem : EntitySystem
SubscribeLocalEvent<MechPilotComponent, GetMeleeWeaponEvent>(OnGetMeleeWeapon);
SubscribeLocalEvent<MechPilotComponent, CanAttackFromContainerEvent>(OnCanAttackFromContainer);
SubscribeLocalEvent<MechPilotComponent, AttackAttemptEvent>(OnAttackAttempt);
SubscribeLocalEvent<MechPilotComponent, EntGotRemovedFromContainerMessage>(OnEntGotRemovedFromContainer);
SubscribeLocalEvent<MechEquipmentComponent, ShotAttemptedEvent>(OnShotAttempted); // Goobstation
Subs.CVar(_config, GoobCVars.MechGunOutsideMech, value => _canUseMechGunOutside = value, true); // Goobstation
}
// GoobStation: Fixes scram implants or teleports locking the pilot out of being able to move.
private void OnEntGotRemovedFromContainer(EntityUid uid, MechPilotComponent component, EntGotRemovedFromContainerMessage args)
{
TryEject(component.Mech, pilot: uid);
}
private void OnToggleEquipmentAction(EntityUid uid, MechComponent component, MechToggleEquipmentEvent args)
@ -368,6 +392,7 @@ public abstract class SharedMechSystem : EntitySystem
SetupUser(uid, toInsert.Value);
_container.Insert(toInsert.Value, component.PilotSlot);
UpdateAppearance(uid, component);
UpdateHands(toInsert.Value, uid, true); // Goobstation
return true;
}
@ -376,23 +401,64 @@ public abstract class SharedMechSystem : EntitySystem
/// </summary>
/// <param name="uid"></param>
/// <param name="component"></param>
/// <param name="pilot">The pilot to eject</param>
/// <returns>Whether or not the pilot was ejected.</returns>
public bool TryEject(EntityUid uid, MechComponent? component = null)
public bool TryEject(EntityUid uid, MechComponent? component = null, EntityUid? pilot = null)
{
if (!Resolve(uid, ref component))
return false;
if (component.PilotSlot.ContainedEntity == null)
if (component.PilotSlot.ContainedEntity != null)
pilot = component.PilotSlot.ContainedEntity.Value;
if (pilot == null)
return false;
var pilot = component.PilotSlot.ContainedEntity.Value;
RemoveUser(uid, pilot);
_container.RemoveEntity(uid, pilot);
RemoveUser(uid, pilot.Value);
_container.RemoveEntity(uid, pilot.Value);
UpdateAppearance(uid, component);
UpdateHands(pilot.Value, uid, false); // Goobstation
return true;
}
// Goobstation Change Start
private void UpdateHands(EntityUid uid, EntityUid mech, bool active)
{
if (!TryComp<HandsComponent>(uid, out var handsComponent))
return;
if (active)
BlockHands(uid, mech, handsComponent);
else
FreeHands(uid, mech);
}
private void BlockHands(EntityUid uid, EntityUid mech, HandsComponent handsComponent)
{
var freeHands = 0;
foreach (var hand in _hands.EnumerateHands(uid, handsComponent))
{
if (hand.HeldEntity == null)
{
freeHands++;
continue;
}
// Is this entity removable? (they might have handcuffs on)
if (HasComp<UnremoveableComponent>(hand.HeldEntity) && hand.HeldEntity != mech)
continue;
_hands.DoDrop(uid, hand, true, handsComponent);
freeHands++;
if (freeHands == 2)
break;
}
if (_virtualItem.TrySpawnVirtualItemInHand(mech, uid, out var virtItem1))
EnsureComp<UnremoveableComponent>(virtItem1.Value);
if (_virtualItem.TrySpawnVirtualItemInHand(mech, uid, out var virtItem2))
EnsureComp<UnremoveableComponent>(virtItem2.Value);
}
private void FreeHands(EntityUid uid, EntityUid mech)
{
_virtualItem.DeleteInHandsMatching(uid, mech);
}
// Goobstation Change End
private void OnGetMeleeWeapon(EntityUid uid, MechPilotComponent component, GetMeleeWeaponEvent args)
{
if (args.Handled)
@ -417,6 +483,20 @@ public abstract class SharedMechSystem : EntitySystem
args.Cancel();
}
// Goobstation: Prevent guns being used out of mechs if CCVAR is set.
private void OnShotAttempted(EntityUid uid, MechEquipmentComponent component, ref ShotAttemptedEvent args)
{
if (!component.EquipmentOwner.HasValue
|| !HasComp<MechComponent>(component.EquipmentOwner.Value))
{
if (!_canUseMechGunOutside)
args.Cancel();
return;
}
var ev = new HandleMechEquipmentBatteryEvent();
RaiseLocalEvent(uid, ev);
}
private void UpdateAppearance(EntityUid uid, MechComponent? component = null,
AppearanceComponent? appearance = null)
{
@ -476,3 +556,12 @@ public sealed partial class MechExitEvent : SimpleDoAfterEvent
public sealed partial class MechEntryEvent : SimpleDoAfterEvent
{
}
/// <summary>
/// Event raised when an user attempts to fire a mech weapon to check if its battery is drained
/// </summary>
[Serializable, NetSerializable]
public sealed partial class HandleMechEquipmentBatteryEvent : EntityEventArgs
{
}

View File

@ -1,5 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared._EE.Silicon.Components; // Goobstation
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
using Content.Shared.Examine;
@ -532,7 +533,7 @@ public abstract class SharedMindSystem : EntitySystem
/// <summary>
/// Returns a list of every living humanoid player's minds, except for a single one which is exluded.
/// </summary>
public HashSet<Entity<MindComponent>> GetAliveHumans(EntityUid? exclude = null)
public HashSet<Entity<MindComponent>> GetAliveHumans(EntityUid? exclude = null, bool excludeSilicon = false)
{
var allHumans = new HashSet<Entity<MindComponent>>();
// HumanoidAppearanceComponent is used to prevent mice, pAIs, etc from being chosen
@ -544,6 +545,10 @@ public abstract class SharedMindSystem : EntitySystem
if (!TryGetMind(uid, out var mind, out var mindComp) || mind == exclude || !_mobState.IsAlive(uid, mobState))
continue;
// Goobstation: Skip IPCs from selections
if (excludeSilicon && HasComp<SiliconComponent>(uid))
continue;
allHumans.Add(new Entity<MindComponent>(mind, mindComp));
}

View File

@ -72,7 +72,7 @@ public sealed partial class MeleeWeaponComponent : Component
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public bool ResistanceBypass = false;
/// <summary>
/// Base damage for this weapon. Can be modified via heavy damage or other means.
/// </summary>
@ -170,6 +170,10 @@ public sealed partial class MeleeWeaponComponent : Component
public float HeavyPartDamageMultiplier = 0.5f;
// Shitmed Change End
// Goobstation
[DataField, AutoNetworkedField]
public bool CanWideSwing = true;
}
/// <summary>

View File

@ -191,7 +191,8 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
return;
if (!TryGetWeapon(user, out var weaponUid, out var weapon) ||
weaponUid != GetEntity(msg.Weapon))
weaponUid != GetEntity(msg.Weapon) ||
!weapon.CanWideSwing) // Goobstation Change
{
return;
}

View File

@ -17,4 +17,14 @@ public sealed partial class GoobCVars
/// </summary>
public static readonly CVarDef<bool> AutoGetUp =
CVarDef.Create("white.auto_get_up", true, CVar.CLIENT | CVar.ARCHIVE | CVar.REPLICATED); // WD EDIT
#region Mechs
/// <summary>
/// Whether or not players can use mech guns outside of mechs.
/// </summary>
public static readonly CVarDef<bool> MechGunOutsideMech =
CVarDef.Create("mech.gun_outside_mech", true, CVar.SERVER | CVar.REPLICATED);
#endregion
}

View File

@ -42,6 +42,7 @@
enum.MechUiKey.Key:
type: MechBoundUserInterface
- type: MeleeWeapon
canWideSwing: false
hidden: true
attackRate: 0.75
damage:

View File

@ -0,0 +1,7 @@
- type: damageModifierSet
id: IPC
coefficients:
Poison: 0
Cold: 0.2
Heat: 2
Shock: 2.5

View File

@ -38,6 +38,18 @@
# safe: false
# - type: EyeProtection # You'll want this if your robot can't wear glasses, like an IPC.
# protectionTime: 12
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeCircle
radius: 0.35
density: 185
restitution: 0.0
mask:
- MobMask
layer:
- MobLayer
- type: Silicon
entityType: enum.SiliconType.Player
batteryPowered: false # Needs to also have a battery!
@ -299,11 +311,3 @@
- type: Targeting
- type: SurgeryTarget
- type: LayingDown
- type: damageModifierSet
id: IPC
coefficients:
Poison: 0
Cold: 0.2
Heat: 2
Shock: 2.5