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

Blood Cult DLC 1: Make It an Actually Playable Game (Mode) #1276

Merged
merged 24 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
452a5f6
feat: construct actions
Remuchi Nov 24, 2024
51cffcc
fix: killing last cultist no longer finishes round
Remuchi Nov 24, 2024
9f09f1b
fix: maybe fix metadata in cult objective
Remuchi Nov 24, 2024
988fa06
feat: rending rune placement system
Remuchi Nov 24, 2024
59ad033
fix: a few fixes with rending rune markers
Remuchi Nov 24, 2024
57c2a89
fix: fixed teleport spell
Remuchi Nov 24, 2024
ea85137
fix: fixed timed factory being able to produce infinite items
Remuchi Nov 24, 2024
d6befd0
fix: fixed offering target selection
Remuchi Nov 24, 2024
6b9a11e
feat: placement marker for rending runes
Remuchi Nov 24, 2024
15fc1c3
fix: a bunch of bugfixes
Remuchi Nov 25, 2024
1044cae
Merge branch 'einstein-engines' into feat/blood-cult-dlc-1
rbertoche Dec 9, 2024
fc1da8e
Merge pull request #1 from rbertoche/feat/blood-cult-dlc-1
Remuchi Dec 9, 2024
600430d
fix: shadow shackles no longer cuff cultist themselves (lmao)
Remuchi Dec 9, 2024
13246ee
Merge branch 'feat/blood-cult-dlc-1' of https://github.com/Remuchi/Ei…
Remuchi Dec 9, 2024
0b9c5c2
fix: fixed offering not working (hopefuly)
Remuchi Dec 9, 2024
d98586c
fix: nerf blood spear a bit
Remuchi Dec 9, 2024
a343ff5
feat: blood rites improvements
Remuchi Dec 9, 2024
de82bc9
feat: cult guide
Remuchi Dec 9, 2024
7fd44e3
Apply suggestions from code review
Remuchi Dec 9, 2024
44d09f0
fix: stop complaining
Remuchi Dec 10, 2024
19bb64a
Merge branch 'feat/blood-cult-dlc-1' of https://github.com/Remuchi/Ei…
Remuchi Dec 10, 2024
bca8d8f
fix: spawn on world position
Remuchi Dec 10, 2024
dfe8fc9
fix: please I beg you
Remuchi Dec 11, 2024
b19e754
Update SoulShardSystem.cs
VMSolidus Dec 11, 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
2 changes: 1 addition & 1 deletion Content.Client/ListViewSelector/ListViewSelectorBUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ private void PopulateWindow(List<ListViewSelectorEntry> items)
{
var itemName = item.Name;
var itemDesc = item.Description;
if (_prototypeManager.TryIndex(item.Id, out var itemPrototype))
if (_prototypeManager.TryIndex(item.Id, out var itemPrototype, false))
{
itemName = itemPrototype.Name;
itemDesc = itemPrototype.Description;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Content.Shared.WhiteDream.BloodCult.Constructs.PhaseShift;

namespace Content.Client.WhiteDream.BloodCult.PhaseShift;

public sealed class PhaseShiftSystem : SharedPhaseShiftSystem;
61 changes: 29 additions & 32 deletions Content.Client/WhiteDream/BloodCult/Runes/UI/RuneDrawerBUI.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Linq;
using System.Numerics;
using System.Numerics;
using Content.Client.UserInterface.Controls;
using Content.Shared.WhiteDream.BloodCult.Runes;
using JetBrains.Annotations;
Expand All @@ -23,71 +22,72 @@ public sealed class RuneDrawerBUI : BoundUserInterface
[Dependency] private readonly IInputManager _inputManager = default!;

private readonly SpriteSystem _spriteSystem;

private RadialMenu? _menu;
private readonly RadialMenu _menu;

public RuneDrawerBUI(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
_spriteSystem = _entManager.System<SpriteSystem>();
_menu = new()
{
HorizontalExpand = true,
VerticalExpand = true,
BackButtonStyleClass = "RadialMenuBackButton",
CloseButtonStyleClass = "RadialMenuCloseButton"
};
}

protected override void Open()
{
_menu = FormMenu();
_menu.OnClose += Close;
_menu.OpenCenteredAt(_inputManager.MouseScreenPosition.Position / _displayManager.ScreenSize);
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
_menu?.Dispose();
_menu.Close();
}

private RadialMenu FormMenu()
protected override void UpdateState(BoundUserInterfaceState state)
{
var menu = new RadialMenu
{
HorizontalExpand = true,
VerticalExpand = true,
BackButtonStyleClass = "RadialMenuBackButton",
CloseButtonStyleClass = "RadialMenuCloseButton"
};

if (!_entManager.HasComponent<RuneDrawerComponent>(Owner))
return menu;
if (state is RuneDrawerMenuState runeDrawerState)
FillMenu(runeDrawerState.AvailalbeRunes);
}

var runeSelectorArray = _protoManager.EnumeratePrototypes<RuneSelectorPrototype>().OrderBy(r => r.ID).ToArray();
private void FillMenu(List<ProtoId<RuneSelectorPrototype>>? runes = null)
{
if (runes is null)
return;

var mainContainer = new RadialContainer
var container = new RadialContainer
{
Radius = 36f / (runeSelectorArray.Length == 1
? 1
: MathF.Sin(MathF.PI / runeSelectorArray.Length))
Radius = 48f + 24f * MathF.Log(runes.Count)
};

foreach (var runeSelector in runeSelectorArray)
_menu.AddChild(container);

foreach (var runeSelector in runes)
{
if (!_protoManager.TryIndex(runeSelector.Prototype, out var proto))
if (!_protoManager.TryIndex(runeSelector, out var runeSelectorProto) ||
!_protoManager.TryIndex(runeSelectorProto.Prototype, out var runeProto))
continue;

var itemSize = new Vector2(64f, 64f);
var button = new RadialMenuTextureButton
{
ToolTip = Loc.GetString(proto.Name),
ToolTip = Loc.GetString(runeProto.Name),
StyleClasses = { "RadialMenuButton" },
SetSize = itemSize
};

var runeIcon = _spriteSystem.Frame0(proto);
var runeIcon = _spriteSystem.Frame0(runeProto);
var runeScale = itemSize / runeIcon.Size;

var texture = new TextureRect
{
VerticalAlignment = Control.VAlignment.Center,
HorizontalAlignment = Control.HAlignment.Center,
Texture = _spriteSystem.Frame0(proto),
Texture = _spriteSystem.Frame0(runeProto),
TextureScale = runeScale
};

Expand All @@ -99,10 +99,7 @@ private RadialMenu FormMenu()
Close();
};

mainContainer.AddChild(button);
container.AddChild(button);
}

menu.AddChild(mainContainer);
return menu;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ public sealed partial class BloodRitesAuraComponent : Component
[DataField]
public FixedPoint2 TotalHealing = 20;

[DataField]
public float PuddleConsumeRadius = 0.5f;

[DataField]
public SoundSpecifier BloodRitesAudio = new SoundPathSpecifier(
new ResPath("/Audio/WhiteDream/BloodCult/rites.ogg"),
Expand Down
58 changes: 47 additions & 11 deletions Content.Server/WhiteDream/BloodCult/BloodRites/BloodRitesSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
using Content.Shared.Damage.Prototypes;
using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.Fluids.Components;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.UserInterface;
Expand All @@ -34,6 +36,7 @@ public sealed class BloodRitesSystem : EntitySystem
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly DoAfterSystem _doAfter = default!;
[Dependency] private readonly HandsSystem _handsSystem = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
Expand All @@ -52,6 +55,8 @@ public override void Initialize()

SubscribeLocalEvent<BloodRitesAuraComponent, BeforeActivatableUIOpenEvent>(BeforeUiOpen);
SubscribeLocalEvent<BloodRitesAuraComponent, BloodRitesMessage>(OnRitesMessage);

SubscribeLocalEvent<BloodRitesAuraComponent, DroppedEvent>(OnDropped);
}

private void OnExamining(Entity<BloodRitesAuraComponent> rites, ref ExaminedEvent args) =>
Expand Down Expand Up @@ -83,19 +88,16 @@ private void OnAfterInteract(Entity<BloodRitesAuraComponent> rites, ref AfterInt
return;
}

if (!TryComp(args.Target, out SolutionContainerManagerComponent? solutionContainer)) // please send help
return;

foreach (var (_, solution) in _solutionContainer.EnumerateSolutions((args.Target.Value, solutionContainer)))
if (HasComp<PuddleComponent>(args.Target))
{
// I don't think something will ever have more than 1000 blood units in it's solution...
rites.Comp.StoredBlood += solution.Comp.Solution.RemoveReagent(_bloodProto, 1000);
_solutionContainer.UpdateChemicals(solution);
break;
ConsumePuddles(args.Target.Value, rites);
args.Handled = true;
}
else if (TryComp(args.Target, out SolutionContainerManagerComponent? solutionContainer))
{
ConsumeBloodFromSolution((args.Target.Value, solutionContainer), rites);
args.Handled = true;
}

_audio.PlayPvs(rites.Comp.BloodRitesAudio, rites);
args.Handled = true;
}

private void OnDoAfter(Entity<BloodRitesAuraComponent> rites, ref BloodRitesExtractDoAfterEvent args)
Expand Down Expand Up @@ -154,6 +156,8 @@ private void OnRitesMessage(Entity<BloodRitesAuraComponent> rites, ref BloodRite
_handsSystem.TryPickup(args.Actor, ent);
}

private void OnDropped(Entity<BloodRitesAuraComponent> rites, ref DroppedEvent args) => QueueDel(rites);

private bool Heal(Entity<BloodRitesAuraComponent> rites, EntityUid user, Entity<DamageableComponent> target)
{
if (target.Comp.TotalDamage == 0)
Expand Down Expand Up @@ -234,4 +238,36 @@ Entity<BloodstreamComponent> target
rites.Comp.StoredBlood -= bloodCost;
return true;
}

private void ConsumePuddles(EntityUid origin, Entity<BloodRitesAuraComponent> rites)
{
var coords = Transform(origin).Coordinates;

var lookup = _lookup.GetEntitiesInRange<PuddleComponent>(
coords,
rites.Comp.PuddleConsumeRadius,
LookupFlags.Uncontained);

foreach (var puddle in lookup)
{
if (!TryComp(puddle, out SolutionContainerManagerComponent? solutionContainer))
continue;
ConsumeBloodFromSolution((puddle, solutionContainer), rites);
}

_audio.PlayPvs(rites.Comp.BloodRitesAudio, rites);
}

private void ConsumeBloodFromSolution(
Entity<SolutionContainerManagerComponent?> ent,
Entity<BloodRitesAuraComponent> rites
)
{
foreach (var (_, solution) in _solutionContainer.EnumerateSolutions(ent))
{
rites.Comp.StoredBlood += solution.Comp.Solution.RemoveReagent(_bloodProto, 1000);
_solutionContainer.UpdateChemicals(solution);
break;
}
}
}
67 changes: 67 additions & 0 deletions Content.Server/WhiteDream/BloodCult/ConstructActionsSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using Content.Server.WhiteDream.BloodCult.Constructs.PhaseShift;
using Content.Shared.StatusEffect;
using Content.Shared.WhiteDream.BloodCult.Spells;
using Robust.Server.Audio;
using Robust.Server.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using PhaseShiftedComponent = Content.Shared.WhiteDream.BloodCult.Constructs.PhaseShift.PhaseShiftedComponent;

namespace Content.Server.WhiteDream.BloodCult;

public sealed class ConstructActionsSystem : EntitySystem
{
[Dependency] private readonly ITileDefinitionManager _tileDef = default!;

[Dependency] private readonly AudioSystem _audio = default!;
sleepyyapril marked this conversation as resolved.
Show resolved Hide resolved
[Dependency] private readonly MapSystem _mapSystem = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;

private const string CultTileSpawnEffect = "CultTileSpawnEffect";

public override void Initialize()
{
SubscribeLocalEvent<PlaceTileEntityEvent>(OnPlaceTileEntityEvent);
SubscribeLocalEvent<PhaseShiftEvent>(OnPhaseShift);
}

private void OnPlaceTileEntityEvent(PlaceTileEntityEvent args)
{
if (args.Handled)
return;

if (args.Entity is { } entProtoId)
Spawn(entProtoId, args.Target);

if (args.TileId is { } tileId)
{
if (_transform.GetGrid(args.Target) is not { } grid || !TryComp(grid, out MapGridComponent? mapGrid))
return;

var tileDef = _tileDef[tileId];
var tile = new Tile(tileDef.TileId);

_mapSystem.SetTile(grid, mapGrid, args.Target, tile);
Spawn(CultTileSpawnEffect, args.Target);
}

if (args.Audio is { } audio)
_audio.PlayPvs(audio, args.Target);

args.Handled = true;
}

private void OnPhaseShift(PhaseShiftEvent args)
{
if (args.Handled)
return;

if (_statusEffects.TryAddStatusEffect<PhaseShiftedComponent>(
args.Performer,
args.StatusEffectId,
args.Duration,
false))
args.Handled = true;
}
}
31 changes: 19 additions & 12 deletions Content.Server/WhiteDream/BloodCult/Constructs/ConstructSystem.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Content.Server.WhiteDream.BloodCult.Gamerule;
using Content.Server.Actions;
using Content.Server.WhiteDream.BloodCult.Gamerule;
using Content.Shared.WhiteDream.BloodCult;
using Content.Shared.WhiteDream.BloodCult.Constructs;
using Robust.Server.GameObjects;
Expand All @@ -7,13 +8,14 @@ namespace Content.Server.WhiteDream.BloodCult.Constructs;

public sealed class ConstructSystem : EntitySystem
{
[Dependency] private readonly ActionsSystem _actions = default!;
[Dependency] private readonly AppearanceSystem _appearanceSystem = default!;

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

SubscribeLocalEvent<ConstructComponent, ComponentStartup>(OnComponentStartup);
SubscribeLocalEvent<ConstructComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<ConstructComponent, ComponentShutdown>(OnComponentShutdown);
}

Expand All @@ -37,23 +39,28 @@ public override void Update(float frameTime)
}
}

private void OnComponentStartup(Entity<ConstructComponent> ent, ref ComponentStartup args)
private void OnMapInit(Entity<ConstructComponent> construct, ref MapInitEvent args)
{
_appearanceSystem.SetData(ent, ConstructVisualsState.Transforming, true);
ent.Comp.Transforming = true;
var cultistRule = EntityManager.EntityQueryEnumerator<BloodCultRuleComponent>();
while (cultistRule.MoveNext(out _, out var rule))
foreach (var actionId in construct.Comp.Actions)
{
rule.Constructs.Add(ent);
var action = _actions.AddAction(construct, actionId);
construct.Comp.ActionEntities.Add(action);
}

_appearanceSystem.SetData(construct, ConstructVisualsState.Transforming, true);
construct.Comp.Transforming = true;
var cultistRule = EntityManager.EntityQueryEnumerator<BloodCultRuleComponent>();
while (cultistRule.MoveNext(out _, out var rule))
rule.Constructs.Add(construct);
}

private void OnComponentShutdown(Entity<ConstructComponent> ent, ref ComponentShutdown args)
private void OnComponentShutdown(Entity<ConstructComponent> construct, ref ComponentShutdown args)
{
foreach (var actionEntity in construct.Comp.ActionEntities)
_actions.RemoveAction(actionEntity);

var cultistRule = EntityManager.EntityQueryEnumerator<BloodCultRuleComponent>();
while (cultistRule.MoveNext(out _, out var rule))
{
rule.Constructs.Remove(ent);
}
rule.Constructs.Remove(construct);
}
}
Loading
Loading