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

Spider queen antag v0.2 #1789

Merged
merged 48 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
e712cad
Spider queen antag v0.2
Kirus59 Sep 7, 2024
d81a662
move actions to unique component
Kirus59 Sep 7, 2024
6ea9913
add mana system
Kirus59 Sep 7, 2024
77a8728
Add cocooning action
Kirus59 Sep 8, 2024
3b76235
Actions optimization and delete needless implants
Kirus59 Sep 9, 2024
b4f5fb6
some optimization
Kirus59 Sep 9, 2024
3271958
add mana generation bonus from cocoons
Kirus59 Sep 10, 2024
b1febd2
Add game rule and some fixes
Kirus59 Sep 12, 2024
565273a
add cocoons sprites and some changes
Kirus59 Sep 13, 2024
35f960b
some fixes...
Kirus59 Sep 13, 2024
c815f98
Game Rule fixes
Kirus59 Sep 13, 2024
81af714
Add cocoons objective
Kirus59 Sep 13, 2024
67697fd
Add survive objective and fixes
Kirus59 Sep 14, 2024
8aa3090
Add mana information into character briefing
Kirus59 Sep 14, 2024
eaeec64
Add station announcement
Kirus59 Sep 14, 2024
90a228c
fix greentext
Kirus59 Sep 14, 2024
7f013b3
Balance changes and some fixes
Kirus59 Sep 14, 2024
8a02278
Create cocoons conditoin fixes
Kirus59 Sep 14, 2024
231f2ff
yaml fixes
Kirus59 Sep 14, 2024
fdbc0ff
Add bonus to MaxMana from cocoons
Kirus59 Sep 15, 2024
fc37ff5
Review fixes
Kirus59 Sep 15, 2024
38c3b0d
Add doAfter to SpiderWorldSpawnEvent, add wallspawn animation and some
Kirus59 Sep 16, 2024
ca62532
ops...
Kirus59 Sep 16, 2024
0eeebb2
Cocoons bonus change
Kirus59 Sep 18, 2024
a751879
Some fixes
Kirus59 Sep 18, 2024
b5b405d
Some fixes 2
Kirus59 Sep 18, 2024
c26efad
Rename mana and some changes
Kirus59 Sep 19, 2024
f9a994d
Some fixes
Kirus59 Sep 19, 2024
74cf73d
Merge branch 'master' into SpiderQueen-antag-v0.1.1
Kirus59 Sep 20, 2024
5b5ea91
Tag fix
Kirus59 Sep 20, 2024
0826754
Add hunger conversion
Kirus59 Sep 20, 2024
a7e7229
Mother of balance
Kirus59 Sep 20, 2024
82ef5d9
some fixes
Kirus59 Sep 20, 2024
cd1a7dd
change actions description and some changes
Kirus59 Sep 20, 2024
5c44633
Merge branch 'master' into SpiderQueen-antag-v0.1.1
Kirus59 Sep 23, 2024
b79beff
some changes
Kirus59 Sep 23, 2024
73b02d7
yaml fixes
Kirus59 Sep 23, 2024
4b8e114
fix cocoons damage per second
Kirus59 Sep 23, 2024
dafda3b
balance changes
Kirus59 Oct 2, 2024
ff72d0b
add alert for blood points and some fixes
Kirus59 Oct 2, 2024
2b4f8b5
add alert name and desc
Kirus59 Oct 3, 2024
13efb90
post-review fixes
Kirus59 Oct 4, 2024
6117b47
forgot add to BasicAntagEventsTable
Kirus59 Oct 4, 2024
bb2607b
some optimization
Kirus59 Oct 5, 2024
446b419
post-tests fixes
Kirus59 Oct 8, 2024
ef6f42b
delete needless usings
Kirus59 Oct 8, 2024
5ef1456
delete needless using and dependency
Kirus59 Oct 8, 2024
c2c67a0
delete needless comment
Kirus59 Oct 9, 2024
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
3 changes: 3 additions & 0 deletions Content.Server/Roles/RoleSystem.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Content.Server.SS220.Roles;
using Content.Shared.Roles;
using Content.Shared.SS220.DarkReaper;
using Content.Shared.SS220.MindSlave;
Expand All @@ -24,6 +25,8 @@ public override void Initialize()
SubscribeAntagEvents<MindSlaveRoleComponent>();
//SS220 DarkReaper
SubscribeAntagEvents<DarkReaperRoleComponent>();
//SS220 Spider queen
SubscribeAntagEvents<SpiderQueenRoleComponent>();
}

public string? MindGetBriefing(EntityUid? mindId)
Expand Down
7 changes: 7 additions & 0 deletions Content.Server/SS220/Markers/AntagSpawnMarkerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt
namespace Content.Server.SS220.Markers;

[RegisterComponent]
public sealed partial class AntagSpawnMarkerComponent : Component
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt
namespace Content.Server.SS220.Objectives.Components;

[RegisterComponent]
public sealed partial class CreateCocoonsConditionComponent : Component
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt
using Content.Server.Objectives.Systems;
using Content.Server.SS220.Objectives.Components;
using Content.Server.SS220.Roles;
using Content.Shared.Mind;
using Content.Shared.Objectives.Components;
using Content.Shared.SS220.SpiderQueen.Components;

namespace Content.Server.SS220.Objectives.Systems;

public sealed partial class CreateCocoonsConditionSystem : EntitySystem
{
[Dependency] private readonly NumberObjectiveSystem _number = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<CreateCocoonsConditionComponent, ObjectiveGetProgressEvent>(OnGetProgress);
}

private void OnGetProgress(Entity<CreateCocoonsConditionComponent> ent, ref ObjectiveGetProgressEvent args)
{
args.Progress = GetProgress(args.MindId, args.Mind, _number.GetTarget(ent.Owner));
}

private float GetProgress(EntityUid mindId, MindComponent mind, int target)
{
if (!TryComp<SpiderQueenRoleComponent>(mindId, out var spiderQueenRole))
return 0f;

if (spiderQueenRole.IsCreateCocoonsCompletedOnce)
return 1f;

var mobUid = mind.CurrentEntity;
if (mobUid is null ||
!TryComp<SpiderQueenComponent>(mobUid, out var spiderQueen))
return 0f;

if (spiderQueen.CocoonsList.Count >= target)
{
spiderQueenRole.IsCreateCocoonsCompletedOnce = true;
return 1f;
}
else
{
return 0f;
}
}
}
11 changes: 11 additions & 0 deletions Content.Server/SS220/Roles/SpiderQueenRoleComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt
using Content.Shared.Roles;

namespace Content.Server.SS220.Roles;

[RegisterComponent, ExclusiveAntagonist]
public sealed partial class SpiderQueenRoleComponent : AntagonistRoleComponent
{
[ViewVariables]
public bool IsCreateCocoonsCompletedOnce = false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt
using Content.Shared.Whitelist;

namespace Content.Server.SS220.SpiderQueen.Components;

[RegisterComponent]
public sealed partial class SpiderQueenRuleComponent : Component
{
/// <summary>
/// Spawn on a random entity that passed whitelist.
/// If null - spawn on a random tile.
/// </summary>
[DataField]
public EntityWhitelist? MarkersWhitelist;
}
175 changes: 175 additions & 0 deletions Content.Server/SS220/SpiderQueen/Systems/SpiderCocoonSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Server.DoAfter;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.FixedPoint;
using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.SS220.SpiderQueen;
using Content.Shared.SS220.SpiderQueen.Components;
using Content.Shared.Verbs;
using Robust.Shared.Containers;
using Robust.Shared.Timing;

namespace Content.Server.SS220.SpiderQueen.Systems;

public sealed partial class SpiderCocoonSystem : EntitySystem
{
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly DoAfterSystem _doAfter = default!;
[Dependency] private readonly SpiderQueenSystem _spiderQueen = default!;
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
[Dependency] private readonly HungerSystem _hunger = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<SpiderCocoonComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<SpiderCocoonComponent, ExaminedEvent>(OnExamine);
SubscribeLocalEvent<SpiderCocoonComponent, GetVerbsEvent<AlternativeVerb>>(OnAlternativeVerb);
SubscribeLocalEvent<SpiderCocoonComponent, CocoonExtractBloodPointsEvent>(OnExtractBloodPoints);
}

public override void Update(float frameTime)
{
base.Update(frameTime);

var query = EntityQueryEnumerator<SpiderCocoonComponent>();
while (query.MoveNext(out var uid, out var component))
{
if (_gameTiming.CurTime < component.NextSecond)
continue;

component.NextSecond = _gameTiming.CurTime + TimeSpan.FromSeconds(1);
if (!_container.TryGetContainer(uid, component.CocoonContainerId, out var container) ||
container.ContainedEntities is not { } entities ||
entities.Count <= 0)
continue;

foreach (var entity in entities)
{
ConvertBloodIntoBloodPoints(uid, component, entity, component.BloodConversionPerSecond);
CauseCocoonDamage(uid, component, entity);
}
}
}

private void OnShutdown(Entity<SpiderCocoonComponent> entity, ref ComponentShutdown args)
{
var (uid, comp) = entity;
if (comp.CocoonOwner is null ||
!TryComp<SpiderQueenComponent>(comp.CocoonOwner, out var queenComponent))
return;

queenComponent.CocoonsList.Remove(uid);
queenComponent.MaxBloodPoints -= entity.Comp.BloodPointsBonus;
}

private void OnExamine(Entity<SpiderCocoonComponent> entity, ref ExaminedEvent args)
{
if (HasComp<SpiderQueenComponent>(args.Examiner))
{
args.PushMarkup(Loc.GetString("spider-cocoon-blood-points-amount", ("amount", entity.Comp.BloodPointsAmount)));
}
}

private void OnAlternativeVerb(EntityUid uid, SpiderCocoonComponent component, GetVerbsEvent<AlternativeVerb> args)
{
if (!args.CanAccess ||
!TryComp<SpiderQueenComponent>(args.User, out var spiderQueen))
return;

var extractVerb = new AlternativeVerb
{
Text = Loc.GetString("spider-cocoon-extract-blood-points-verb"),
Act = () =>
{
var doAfterEventArgs = new DoAfterArgs(EntityManager,
args.User,
spiderQueen.CocoonExtractTime,
new CocoonExtractBloodPointsEvent(),
uid,
uid)
{
Broadcast = false,
BreakOnDamage = false,
BreakOnMove = true,
NeedHand = false,
BlockDuplicate = true,
CancelDuplicate = true,
DuplicateCondition = DuplicateConditions.SameEvent
};

_doAfter.TryStartDoAfter(doAfterEventArgs);
}
};

args.Verbs.Add(extractVerb);
}

private void OnExtractBloodPoints(Entity<SpiderCocoonComponent> entity, ref CocoonExtractBloodPointsEvent args)
{
if (args.Cancelled ||
!TryComp<SpiderQueenComponent>(args.User, out var spiderQueen))
return;

var amountToMax = spiderQueen.MaxBloodPoints - spiderQueen.CurrentBloodPoints;
var extractedValue = MathF.Min((float)amountToMax, (float)entity.Comp.BloodPointsAmount);
entity.Comp.BloodPointsAmount -= extractedValue;
spiderQueen.CurrentBloodPoints += extractedValue;

_hunger.ModifyHunger(args.User, extractedValue * spiderQueen.HungerExtractCoefficient);

Dirty(args.User, spiderQueen);
Dirty(entity);
_spiderQueen.UpdateAlert((args.User, spiderQueen));
}

/// <summary>
/// Converts entity blood into blood points based on the <see cref="SpiderCocoonComponent.BloodConversionCoefficient"/>
/// </summary>
private void ConvertBloodIntoBloodPoints(EntityUid uid, SpiderCocoonComponent component, EntityUid target, FixedPoint2 amount)
{
if (!TryComp<BloodstreamComponent>(target, out var bloodstream) ||
!_solutionContainer.ResolveSolution(target, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution))
return;

var solutionEnt = bloodstream.BloodSolution.Value;
if (solutionEnt.Comp.Solution.Volume <= FixedPoint2.Zero)
return;

_bloodstream.TryModifyBleedAmount(target, -1f, bloodstream);
_solutionContainer.SplitSolution(solutionEnt, amount);
component.BloodPointsAmount += amount * component.BloodConversionCoefficient;
Dirty(uid, component);
}

private void CauseCocoonDamage(EntityUid uid, SpiderCocoonComponent component, EntityUid target)
{
if (!TryComp<DamageableComponent>(target, out var damageable) ||
component.DamagePerSecond is not { } damagePerSecond)
return;

DamageSpecifier causedDamage = new();
foreach (var damage in damagePerSecond.DamageDict)
{
var (type, value) = damage;
if (component.DamageCap.TryGetValue(type, out var cap) &&
damageable.Damage.DamageDict.TryGetValue(type, out var total) &&
total >= cap)
continue;

causedDamage.DamageDict.Add(type, value);
}

_damageable.TryChangeDamage(target, causedDamage, true);
Dirty(uid, component);
}
}
95 changes: 95 additions & 0 deletions Content.Server/SS220/SpiderQueen/Systems/SpiderQueenRuleSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt
using Content.Server.Antag;
using Content.Server.GameTicking.Rules;
using Content.Server.Mind;
using Content.Server.Respawn;
using Content.Server.Roles;
using Content.Server.SS220.Markers;
using Content.Server.SS220.Roles;
using Content.Server.SS220.SpiderQueen.Components;
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Shared.Whitelist;
using Robust.Shared.Map;

namespace Content.Server.SS220.SpiderQueen.Systems;

public sealed class SpiderQueenRuleSystem : GameRuleSystem<SpiderQueenRuleComponent>
{
[Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly SpecialRespawnSystem _specialRespawn = default!;
[Dependency] private readonly MindSystem _mind = default!;
[Dependency] private readonly AntagSelectionSystem _antag = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<SpiderQueenRuleComponent, AntagSelectLocationEvent>(OnAntagSelectLocation);
SubscribeLocalEvent<SpiderQueenRuleComponent, AfterAntagEntitySelectedEvent>(AfterEntitySelected);

SubscribeLocalEvent<SpiderQueenRoleComponent, GetBriefingEvent>(OnGetBriefing);
}

private void OnAntagSelectLocation(Entity<SpiderQueenRuleComponent> ent, ref AntagSelectLocationEvent args)
{
if (args.Handled)
return;

List<MapCoordinates> validCoordinates = new();
var query = EntityQueryEnumerator<AntagSpawnMarkerComponent>();
while (query.MoveNext(out var uid, out _))
{
if (_entityWhitelist.IsWhitelistFail(ent.Comp.MarkersWhitelist, uid) ||
!TryComp<TransformComponent>(uid, out var transform))
continue;

validCoordinates.Add(_transform.ToMapCoordinates(transform.Coordinates));
}

if (validCoordinates.Count > 0)
args.Coordinates = validCoordinates;
else
{
EntityUid? grid = null;
EntityUid? map = null;
foreach (var station in _station.GetStationsSet())
{
if (!TryComp<StationDataComponent>(station, out var data))
continue;

grid = _station.GetLargestGrid(data);
if (!grid.HasValue)
continue;

map = Transform(grid.Value).MapUid;
if (!map.HasValue)
continue;

break;
}

if (grid.HasValue && map.HasValue &&
_specialRespawn.TryFindRandomTile(grid.Value, map.Value, 30, out var randomCoords))
args.Coordinates.Add(_transform.ToMapCoordinates(randomCoords));
}
}

private void AfterEntitySelected(Entity<SpiderQueenRuleComponent> ent, ref AfterAntagEntitySelectedEvent args)
{
var spider = args.EntityUid;
if (!_mind.TryGetMind(spider, out var mindId, out var mind))
return;

var briefing = Loc.GetString("spider-queen-role-greeting");
_antag.SendBriefing(spider, briefing, null, null);
}

private void OnGetBriefing(Entity<SpiderQueenRoleComponent> ent, ref GetBriefingEvent args)
{
var briefing = Loc.GetString("spider-queen-role-greeting");
args.Append(briefing);
}
}
Loading
Loading