Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port Arachne & Oniro from EE, with some DV changes along the way #2817

Draft
wants to merge 33 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
729ed02
meow
Lyndomen Nov 15, 2024
b29be67
Merge branch 'master' into spiderwife
Lyndomen Nov 15, 2024
86c35bc
Merge branch 'DeltaV-Station:master' into spiderwife
Lyndomen Jan 14, 2025
ea42b14
sppoder
Lyndomen Jan 14, 2025
cd019ae
Merge branch 'DeltaV-Station:master' into spiderwife
Lyndomen Jan 14, 2025
3db2afc
spoder
Lyndomen Jan 15, 2025
d425c5d
spoder
Lyndomen Jan 16, 2025
6ed40ee
Merge branch 'DeltaV-Station:master' into spiderwife
Lyndomen Jan 20, 2025
5c995eb
arachne real
Lyndomen Jan 20, 2025
433f86e
aaaaaaaaa
Lyndomen Jan 23, 2025
916a37e
spider
Lyndomen Jan 29, 2025
87c969f
Merge branch 'DeltaV-Station:master' into spiderwife
Lyndomen Jan 29, 2025
e2af2b4
take 10
Lyndomen Jan 29, 2025
e140b5b
aaaa
Lyndomen Jan 29, 2025
e9e070e
succ to suck, not funny
Lyndomen Jan 29, 2025
dc44811
removesucc 2
Lyndomen Jan 29, 2025
7260355
refactor gaming
Lyndomen Jan 29, 2025
b15e4a6
spider real
Lyndomen Jan 29, 2025
a54bc84
Merge branch 'master' into spiderwife
Lyndomen Jan 29, 2025
a2c3067
yaml
Lyndomen Jan 30, 2025
f0fe39f
arachne damage mods
Lyndomen Jan 30, 2025
5163f72
namespace
Lyndomen Jan 30, 2025
23709c7
migrate namespace 2
Lyndomen Jan 30, 2025
b9f6e70
namespace 3
Lyndomen Jan 30, 2025
0bf7c9b
namespace 4 real
Lyndomen Jan 30, 2025
0603811
Update chitinid.ftl
Lyndomen Jan 31, 2025
136e701
Update item-cougher.ftl
Lyndomen Jan 31, 2025
22ba57a
Update lifedrainer.ftl
Lyndomen Jan 31, 2025
ba0707d
move to shared gaming
Lyndomen Jan 31, 2025
fc5c04c
Merge remote-tracking branch 'origin/spider-dating-sim' into spider-d…
Lyndomen Jan 31, 2025
6a9f767
migrate to shared and small refactor
Lyndomen Feb 3, 2025
e7faa92
i have no idea B)
Lyndomen Feb 4, 2025
3103a87
a
Lyndomen Feb 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions Content.Client/_DV/Cocoon/CocoonSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Numerics;
using Content.Shared._DV.Cocoon;
using Content.Shared.Humanoid;
using Robust.Client.GameObjects;
using Robust.Shared.Containers;

namespace Content.Client._DV.Cocoon
{
public sealed class CocoonSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<CocoonComponent, EntInsertedIntoContainerMessage>(OnCocEntInserted);
}

private void OnCocEntInserted(EntityUid uid, CocoonComponent component, EntInsertedIntoContainerMessage args)
{
if (!TryComp<SpriteComponent>(uid, out var cocoonSprite))
return;

if (TryComp<HumanoidAppearanceComponent>(args.Entity, out var humanoidAppearance)) // If humanoid, use height and width
cocoonSprite.Scale = new Vector2(1,1);
else if (!TryComp<SpriteComponent>(args.Entity, out var entSprite))
return;
else if (entSprite.BaseRSI != null) // Set scale based on sprite scale + sprite dimensions. Ideally we would somehow get a bounding box from the sprite size not including transparent pixels, but FUCK figuring that out.
cocoonSprite.Scale = entSprite.Scale * (entSprite.BaseRSI.Size / 32);
else if (entSprite.Scale != cocoonSprite.Scale) // if basersi somehow not found (?) just use scale
cocoonSprite.Scale = entSprite.Scale;
}
}
}
62 changes: 62 additions & 0 deletions Content.Server/_DV/Cocoon/CocoonerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using Content.Server.DoAfter;
using Content.Server.Popups;
using Content.Server.Speech.Components;
using Content.Shared._DV.Cocoon;
using Content.Shared.Administration.Logs;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Damage;
using Content.Shared.Destructible;
using Content.Shared.Eye.Blinding.Systems;
using Content.Shared.Stunnable;
using Robust.Shared.Containers;
using Robust.Shared.Random;

namespace Content.Server._DV.Cocoon
{
public sealed class CocooningSystem : EntitySystem
{
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly DoAfterSystem _doAfter = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
[Dependency] private readonly BlindableSystem _blindableSystem = default!;
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly SharedDestructibleSystem _destructibleSystem = default!;
[Dependency] private readonly IRobustRandom _robustRandom = default!;

private const string BodySlot = "body_slot";

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CocoonComponent, EntInsertedIntoContainerMessage>(OnCocEntInserted);
SubscribeLocalEvent<CocoonComponent, EntRemovedFromContainerMessage>(OnCocEntRemoved);
}

private void OnCocEntInserted(EntityUid uid, CocoonComponent component, EntInsertedIntoContainerMessage args)
{
component.Victim = args.Entity;

if (TryComp<ReplacementAccentComponent>(args.Entity, out var currentAccent))
component.OldAccent = currentAccent.Accent;

EnsureComp<ReplacementAccentComponent>(args.Entity).Accent = "mumble";
EnsureComp<StunnedComponent>(args.Entity);

_blindableSystem.UpdateIsBlind(args.Entity);
}

private void OnCocEntRemoved(EntityUid uid, CocoonComponent component, EntRemovedFromContainerMessage args)
{
if (TryComp<ReplacementAccentComponent>(args.Entity, out var replacement))
if (component.OldAccent is not null)
replacement.Accent = component.OldAccent;
else
RemComp(args.Entity, replacement);


RemComp<StunnedComponent>(args.Entity);
_blindableSystem.UpdateIsBlind(args.Entity);
}
}
}
171 changes: 171 additions & 0 deletions Content.Server/_DV/Vampire/BloodSuckerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
using System.Linq;
using Content.Shared.Verbs;
using Content.Shared.Damage;
using Content.Shared.DoAfter;
using Content.Shared.Interaction;
using Content.Shared.Inventory;
using Content.Shared._DV.Vampire;
using Content.Shared._DV.Cocoon;
using Content.Server.Atmos.Components;
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Shared.Chemistry.EntitySystems;
using Content.Server.Popups;
using Content.Server.DoAfter;
using Content.Server.Nutrition.Components;
using Content.Shared.Vampire;
using Robust.Shared.Utility;

namespace Content.Server.Vampire
{
public sealed class BloodSuckerSystem : EntitySystem
{
[Dependency] private readonly BodySystem _bodySystem = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionSystem = default!;
[Dependency] private readonly PopupSystem _popups = default!;
[Dependency] private readonly DoAfterSystem _doAfter = default!;
[Dependency] private readonly StomachSystem _stomachSystem = default!;
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<BloodSuckerComponent, GetVerbsEvent<InnateVerb>>(AddSuckVerb);
SubscribeLocalEvent<BloodSuckerComponent, BloodSuckDoAfterEvent>(OnDoAfter);
}

private void AddSuckVerb(EntityUid uid, BloodSuckerComponent component, GetVerbsEvent<InnateVerb> args)
{

var victim = args.Target;
var ignoreClothes = false;

if (TryComp<CocoonComponent>(args.Target, out var cocoon))
{
victim = cocoon.Victim ?? args.Target;
ignoreClothes = cocoon.Victim != null;
}
else if (component.WebRequired)
return;

if (!TryComp<BloodstreamComponent>(victim, out var bloodstream) || args.User == victim || !args.CanAccess)
return;

InnateVerb verb = new()
{
Act = () =>
{
StartSuckDoAfter(uid, victim, component, bloodstream, !ignoreClothes); // start doafter
},
Text = Loc.GetString("action-name-suck-blood"),
Icon = new SpriteSpecifier.Texture(new("/Textures/Nyanotrasen/Icons/verbiconfangs.png")),
Priority = 2,
};
args.Verbs.Add(verb);
}


private void OnDoAfter(EntityUid uid, BloodSuckerComponent component, BloodSuckDoAfterEvent args)
{
if (args.Cancelled || args.Handled || args.Args.Target == null)
return;

args.Handled = TrySuck(uid, args.Args.Target.Value);
}

public void StartSuckDoAfter(EntityUid bloodsucker, EntityUid victim, BloodSuckerComponent? bloodSuckerComponent = null, BloodstreamComponent? stream = null, bool doChecks = true)
{
if (!Resolve(bloodsucker, ref bloodSuckerComponent) || !Resolve(victim, ref stream))
return;

if (doChecks)
{
if (!_interactionSystem.InRangeUnobstructed(bloodsucker, victim))
return;

if (_inventorySystem.TryGetSlotEntity(victim, "head", out var headUid) && HasComp<PressureProtectionComponent>(headUid))
{
_popups.PopupEntity(Loc.GetString("bloodsucker-fail-helmet", ("helmet", headUid)), victim, bloodsucker, Shared.Popups.PopupType.Medium);
return;
}

if (_inventorySystem.TryGetSlotEntity(bloodsucker, "mask", out var maskUid) &&
EntityManager.TryGetComponent<IngestionBlockerComponent>(maskUid, out var blocker) &&
blocker.Enabled)
{
_popups.PopupEntity(Loc.GetString("bloodsucker-fail-mask", ("mask", maskUid)), victim, bloodsucker, Shared.Popups.PopupType.Medium);
return;
}
}

if (stream.BloodReagent != "Blood")
_popups.PopupEntity(Loc.GetString("bloodsucker-not-blood", ("target", victim)), victim, bloodsucker, Shared.Popups.PopupType.Medium);
else if (_solutionSystem.PercentFull(victim) != 0)
_popups.PopupEntity(Loc.GetString("bloodsucker-fail-no-blood", ("target", victim)), victim, bloodsucker, Shared.Popups.PopupType.Medium);
else
_popups.PopupEntity(Loc.GetString("bloodsucker-doafter-start", ("target", victim)), victim, bloodsucker, Shared.Popups.PopupType.Medium);

_popups.PopupEntity(Loc.GetString("bloodsucker-doafter-start-victim", ("sucker", bloodsucker)), victim, victim, Shared.Popups.PopupType.LargeCaution);

var args = new DoAfterArgs(EntityManager, bloodsucker, bloodSuckerComponent.Delay, new BloodSuckDoAfterEvent(), bloodsucker, target: victim)
{
BreakOnMove = false,
DistanceThreshold = 2f,
NeedHand = false
};

_doAfter.TryStartDoAfter(args);
}

public bool TrySuck(EntityUid bloodsucker, EntityUid victim, BloodSuckerComponent? bloodsuckerComp = null)


{
var sharedBloodSuckerSystem = EntitySystem.Get<SharedBloodSuckerSystem>();

if (!Resolve(bloodsucker, ref bloodsuckerComp))
return false;
if (!TryValidateVictim(victim))
return false;

if (!TryGetBloodsuckerStomach(bloodsucker, out var stomach))
return false;
if (!sharedBloodSuckerSystem.TryValidateSolution(bloodsucker))
return false;

sharedBloodSuckerSystem.PlayBloodSuckEffects(bloodsucker, victim);
return CompleteBloodSuck(bloodsucker, victim, stomach, bloodsuckerComp);
}

private bool TryValidateVictim(EntityUid victim)
{
if (!TryComp<BloodstreamComponent>(victim, out var bloodstream) || bloodstream.BloodSolution == null)
return false;
return _bloodstreamSystem.GetBloodLevelPercentage(victim, bloodstream) != 0.0f;
}

private bool TryGetBloodsuckerStomach(EntityUid bloodsucker, out StomachComponent stomach)
{
stomach = _bodySystem.GetBodyOrganEntityComps<StomachComponent>(bloodsucker).FirstOrDefault();
return true;
}


private bool CompleteBloodSuck(EntityUid bloodsucker, EntityUid victim, StomachComponent stomach, BloodSuckerComponent bloodsuckerComp)
{
if (!TryComp<BloodstreamComponent>(victim, out var bloodstream) || bloodstream.BloodSolution == null)
return false;

var extractedBlood = _solutionSystem.SplitSolution(bloodstream.BloodSolution.Value, bloodsuckerComp.UnitsToSuck);
_stomachSystem.TryTransferSolution(bloodsucker, extractedBlood, stomach);

DamageSpecifier damage = new();
damage.DamageDict.Add("Piercing", 1);
_damageableSystem.TryChangeDamage(victim, damage, true);

return true;
}
}
}
14 changes: 14 additions & 0 deletions Content.Shared/_DV/Cocoon/CocoonComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Content.Shared._DV.Cocoon
{
[RegisterComponent]
public sealed partial class CocoonComponent : Component
{
public string? OldAccent;

public EntityUid? Victim;

[DataField("damagePassthrough")]
public float DamagePassthrough = 0.5f;

}
}
15 changes: 15 additions & 0 deletions Content.Shared/_DV/Cocoon/CocoonDoAfterEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Content.Shared.DoAfter;
using Robust.Shared.Serialization;

namespace Content.Shared._DV.Cocoon
{
[Serializable, NetSerializable]
public sealed partial class CocoonDoAfterEvent : SimpleDoAfterEvent
{
}

[Serializable, NetSerializable]
public sealed partial class UnCocoonDoAfterEvent : SimpleDoAfterEvent
{
}
}
14 changes: 14 additions & 0 deletions Content.Shared/_DV/Cocoon/CocoonerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Robust.Shared.GameStates;

namespace Content.Shared._DV.Cocoon
{
[RegisterComponent, NetworkedComponent]
public sealed partial class CocoonerComponent : Component
{
[DataField("cocoonDelay")]
public float CocoonDelay = 12f;

[DataField("cocoonKnockdownMultiplier")]
public float CocoonKnockdownMultiplier = 0.5f;
}
}
Loading
Loading