Files
OldThink/Content.Server/_White/Cult/Runes/Systems/CultSystem.Actions.cs
Aviu00 6272da2bb3 Fixes (#289)
* - fix: Ling fixes.

* - fix: Fix ghasp identity.

* - fix: Low temp slowdown fix.

* - fix: Crossbow fix.

* - fix: Fix gamerules.

* - fix: Fix shadow shackles.

* - fix: Cleanup refund.

* - fix: Can't pry runic door.

* - fix: Fix crash.

* - fix: Fix mood.

* - fix: Fix dictionary.
2024-04-21 18:07:27 +03:00

504 lines
19 KiB
C#

using System.Linq;
using System.Numerics;
using Content.Server.Body.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Server.Emp;
using Content.Server.EUI;
using Content.Server._White.Cult.UI;
using Content.Shared._White.Chaplain;
using Content.Shared.Chemistry.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Content.Shared.Fluids.Components;
using Content.Shared.Inventory;
using Content.Shared.Stacks;
using Content.Shared.StatusEffect;
using Content.Shared.Stunnable;
using Content.Shared._White.Cult.Actions;
using Content.Shared._White.Cult.Components;
using Content.Shared._White.Cult.Systems;
using Content.Shared.ActionBlocker;
using Content.Shared.Actions;
using Content.Shared.Cuffs;
using Content.Shared.Cuffs.Components;
using Content.Shared.DoAfter;
using Content.Shared.Maps;
using Content.Shared.Mindshield.Components;
using Content.Shared.Popups;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
using Robust.Shared.Player;
using CultistComponent = Content.Shared._White.Cult.Components.CultistComponent;
namespace Content.Server._White.Cult.Runes.Systems;
public partial class CultSystem
{
[Dependency] private readonly SharedStunSystem _stunSystem = default!;
[Dependency] private readonly SolutionContainerSystem _solutionSystem = default!;
[Dependency] private readonly EmpSystem _empSystem = default!;
[Dependency] private readonly EuiManager _euiManager = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly MapSystem _mapSystem = default!;
[Dependency] private readonly TileSystem _tile = default!;
[Dependency] private readonly BloodSpearSystem _bloodSpear = default!;
[Dependency] private readonly PhysicsSystem _physics = default!;
[Dependency] private readonly HolyWeaponSystem _holyWeapon = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
private const string TileId = "CultFloor";
private const string ConcealedTileId = "CultFloorConcealed";
public void InitializeActions()
{
SubscribeLocalEvent<CultistComponent, CultTwistedConstructionActionEvent>(OnTwistedConstructionAction);
SubscribeLocalEvent<CultistComponent, CultSummonDaggerActionEvent>(OnSummonDaggerAction);
SubscribeLocalEvent<CultistComponent, CultShadowShacklesTargetActionEvent>(OnShadowShackles);
SubscribeLocalEvent<CultistComponent, CultElectromagneticPulseInstantActionEvent>(OnElectromagneticPulse);
SubscribeLocalEvent<CultistComponent, CultSummonCombatEquipmentTargetActionEvent>(OnSummonCombatEquipment);
SubscribeLocalEvent<CultistComponent, CultConcealInstantActionEvent>(OnConcealPresence);
SubscribeLocalEvent<CultistComponent, CultRevealInstantActionEvent>(OnConcealPresence);
SubscribeLocalEvent<CultistComponent, CultBloodRitesInstantActionEvent>(OnBloodRites);
SubscribeLocalEvent<CultistComponent, CultBloodSpearRecallInstantActionEvent>(OnBloodSpearRecall);
SubscribeLocalEvent<CultistComponent, CultTeleportTargetActionEvent>(OnTeleport);
SubscribeLocalEvent<CultistComponent, CultStunTargetActionEvent>(OnStunTarget);
SubscribeLocalEvent<CultistComponent, ActionGettingRemovedEvent>(OnActionRemoved);
SubscribeLocalEvent<CultistComponent, ShacklesEvent>(OnShackles);
}
private void OnShackles(Entity<CultistComponent> ent, ref ShacklesEvent args)
{
if (args.Cancelled || args.Target == null)
return;
if (!TryComp(args.Target, out CuffableComponent? cuffable) || cuffable.Container.ContainedEntities.Count > 0)
return;
var cuffs = Spawn("ShadowShackles", Transform(ent).Coordinates);
var handcuffComponent = EnsureComp<HandcuffComponent>(cuffs);
if (_cuffable.TryAddNewCuffs(args.Target.Value, args.User, cuffs, cuffable, handcuffComponent))
{
SharedCuffableSystem.SetUsed(handcuffComponent, true);
return;
}
QueueDel(cuffs);
}
private void OnActionRemoved(Entity<CultistComponent> ent, ref ActionGettingRemovedEvent args)
{
ent.Comp.SelectedEmpowers.Remove(GetNetEntity(args.Action));
Dirty(ent);
}
private void OnStunTarget(EntityUid uid, CultistComponent component, CultStunTargetActionEvent args)
{
if (args.Target == uid || !TryComp<BloodstreamComponent>(args.Performer, out var bloodstream) ||
!TryComp<StatusEffectsComponent>(args.Target, out var status))
return;
if (_holyWeapon.IsHoldingHolyWeapon(args.Target))
{
_popupSystem.PopupEntity("Сила священного оружия препятствует магии.", args.Performer, args.Performer,
PopupType.MediumCaution);
return;
}
if (HasComp<MindShieldComponent>(args.Target))
{
_popupSystem.PopupEntity("Он имплантирован чипом защиты разума.", args.Performer, args.Performer,
PopupType.MediumCaution);
return;
}
if (!_stunSystem.TryParalyze(args.Target, TimeSpan.FromSeconds(6), true, status) &
!_statusEffectsSystem.TryAddStatusEffect(args.Target, "Muted", TimeSpan.FromSeconds(12), true, "Muted",
status))
return;
_bloodstreamSystem.TryModifyBloodLevel(uid, -10, bloodstream, createPuddle: false);
args.Handled = true;
}
private void OnTeleport(EntityUid uid, CultistComponent component, CultTeleportTargetActionEvent args)
{
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstream) ||
!TryComp<ActorComponent>(uid, out var actor))
return;
if (_holyWeapon.IsHoldingHolyWeapon(args.Target))
{
_popupSystem.PopupEntity("Сила священного оружия препятствует магии.", args.Performer, args.Performer,
PopupType.MediumCaution);
return;
}
if (!HasComp<CultistComponent>(args.Target) && !HasComp<ConstructComponent>(args.Target) &&
_actionBlocker.CanInteract(args.Target, null))
{
_popupSystem.PopupEntity("Цель должна быть культистом, быть скованной или парализованной.", args.Performer,
args.Performer, PopupType.MediumCaution);
return;
}
_bloodstreamSystem.TryModifyBloodLevel(uid, -5, bloodstream, createPuddle: false);
var eui = new TeleportSpellEui(args.Performer, args.Target);
_euiManager.OpenEui(eui, actor.PlayerSession);
eui.StateDirty();
args.Handled = true;
}
private void OnBloodRites(EntityUid uid, CultistComponent component, CultBloodRitesInstantActionEvent args)
{
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstreamComponent))
return;
var bruteDamageGroup = _prototypeManager.Index<DamageGroupPrototype>("Brute");
var burnDamageGroup = _prototypeManager.Index<DamageGroupPrototype>("Burn");
var xform = Transform(uid);
var entitiesInRange = _lookup.GetEntitiesInRange(_transform.GetMapCoordinates(xform), 1.5f);
FixedPoint2 totalBloodAmount = 0f;
var breakLoop = false;
foreach (var solutionEntity in entitiesInRange.ToList())
{
if (breakLoop)
break;
if (!TryComp<PuddleComponent>(solutionEntity, out var puddleComponent))
continue;
if (!_solutionSystem.TryGetSolution(solutionEntity, puddleComponent.SolutionName, out var solution))
continue;
foreach (var solutionContent in solution.Value.Comp.Solution.Contents.ToList())
{
if (solutionContent.Reagent.Prototype != "Blood")
continue;
totalBloodAmount += solutionContent.Quantity;
_bloodstreamSystem.TryModifyBloodLevel(uid, solutionContent.Quantity / 6f, bloodstreamComponent);
_solutionSystem.RemoveReagent((Entity<SolutionComponent>) solution, "Blood", FixedPoint2.MaxValue);
/*if (GetMissingBloodValue(bloodstreamComponent) == 0)
{
breakLoop = true;
}*/
}
}
if (totalBloodAmount == 0f)
return;
component.RitesBloodAmount += totalBloodAmount;
_audio.PlayPvs("/Audio/White/Cult/enter_blood.ogg", uid, AudioParams.Default);
_damageableSystem.TryChangeDamage(uid, new DamageSpecifier(bruteDamageGroup, -20));
_damageableSystem.TryChangeDamage(uid, new DamageSpecifier(burnDamageGroup, -20));
_popupSystem.PopupEntity(Loc.GetString("verb-blood-rites-message", ("blood", component.RitesBloodAmount)), uid,
uid);
args.Handled = true;
}
private static FixedPoint2 GetMissingBloodValue(BloodstreamComponent bloodstreamComponent)
{
return bloodstreamComponent.BloodMaxVolume - bloodstreamComponent.BloodSolution!.Value.Comp.Solution.Volume;
}
private void OnBloodSpearRecall(Entity<CultistComponent> ent, ref CultBloodSpearRecallInstantActionEvent args)
{
if (ent.Comp.BloodSpear == null)
{
_bloodSpear.DetachSpearFromUser(ent);
return;
}
var spear = ent.Comp.BloodSpear.Value;
var xform = Transform(spear);
var coords = _transform.GetWorldPosition(xform);
var userCoords = _transform.GetWorldPosition(ent);
var distance = (userCoords - coords).Length();
if (distance > 10f)
{
_popupSystem.PopupEntity("Копьё слишком далеко!", ent, ent);
return;
}
TryComp<PhysicsComponent>(spear, out var physics);
_physics.SetBodyType(spear, BodyType.Dynamic, body: physics, xform: xform);
_transform.AttachToGridOrMap(spear, xform);
_transform.SetWorldPosition(xform, userCoords);
_handsSystem.TryPickupAnyHand(ent, spear, animate: false);
args.Handled = true;
}
private void OnConcealPresence(EntityUid uid, CultistComponent component, CultConcealPresenceInstantActionEvent args)
{
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstream) ||
!TryComp<TransformComponent>(args.Performer, out var xform))
return;
var conceal = args is CultConcealInstantActionEvent;
var concealableQuery = GetEntityQuery<ConcealableComponent>();
var appearanceQuery = GetEntityQuery<AppearanceComponent>();
const float radius = 5f;
var entitiesInRange = _lookup.GetEntitiesInRange(_transform.GetMapCoordinates(xform), radius);
var success = false;
// Conceal/Reveal runes and structures
foreach (var ent in entitiesInRange)
{
if (!concealableQuery.TryGetComponent(ent, out var concealable) ||
!appearanceQuery.TryGetComponent(ent, out var appearance) ||
!EntityManager.MetaQuery.TryGetComponent(ent, out var meta))
continue;
if (concealable.Concealed == conceal)
continue;
_appearanceSystem.SetData(ent, ConcealableAppearance.Concealed, conceal, appearance);
concealable.Concealed = conceal;
RaiseLocalEvent(ent, new ConcealEvent(conceal));
if (concealable.ChangeMeta)
{
if (conceal)
{
_metaDataSystem.SetEntityName(ent, concealable.ConcealedName, meta);
_metaDataSystem.SetEntityDescription(ent, concealable.ConcealedDesc, meta);
}
else
{
_metaDataSystem.SetEntityName(ent, concealable.RevealedName, meta);
_metaDataSystem.SetEntityDescription(ent, concealable.RevealedDesc, meta);
}
}
Dirty(ent, concealable, meta);
success = true;
}
var gridUid = xform.GridUid;
var pos = xform.Coordinates;
var cultTileDef = (ContentTileDefinition) _tileDefinition[TileId];
var concealedTileDef = (ContentTileDefinition) _tileDefinition[ConcealedTileId];
// Conceal/Reveal tiles
if (TryComp(gridUid, out MapGridComponent? mapGrid))
{
var tileRefs = _mapSystem.GetLocalTilesIntersecting(gridUid.Value, mapGrid,
new Box2(pos.Position + new Vector2(-radius, -radius), pos.Position + new Vector2(radius, radius)));
foreach (var tile in tileRefs)
{
var tilePos = _turf.GetTileCenter(tile);
if (!pos.InRange(EntityManager, _transform, tilePos, radius))
continue;
if (conceal)
{
if (tile.Tile.TypeId != cultTileDef.TileId)
continue;
_tile.ReplaceTile(tile, concealedTileDef);
success = true;
}
else
{
if (tile.Tile.TypeId != concealedTileDef.TileId)
continue;
_tile.ReplaceTile(tile, cultTileDef);
success = true;
}
}
}
if (success)
{
_audio.PlayPvs(conceal ? "/Audio/White/Cult/smoke.ogg" : "/Audio/White/Cult/enter_blood.ogg", uid,
AudioParams.Default.WithMaxDistance(5f));
_bloodstreamSystem.TryModifyBloodLevel(uid, -2, bloodstream, createPuddle: false);
args.Handled = true;
}
var spellQuery = GetEntityQuery<ConcealPresenceSpellComponent>();
var actionQuery = GetEntityQuery<InstantActionComponent>();
// Alter spell concealing/revealing state
foreach (var empower in component.SelectedEmpowers)
{
if (empower == null)
continue;
var ent = GetEntity(empower.Value);
if (!spellQuery.TryGetComponent(ent, out var spell) ||
!actionQuery.TryGetComponent(ent, out var action))
continue;
if (conceal)
{
spell.Revealing = true;
action.Icon = spell.RevealIcon;
action.Event = spell.RevealEvent;
}
else
{
spell.Revealing = false;
action.Icon = spell.ConcealIcon;
action.Event = spell.ConcealEvent;
}
Dirty(ent, action);
}
}
private void OnSummonCombatEquipment(
EntityUid uid,
CultistComponent component,
CultSummonCombatEquipmentTargetActionEvent args)
{
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstream))
return;
_bloodstreamSystem.TryModifyBloodLevel(uid, -20, bloodstream, createPuddle: false);
var coordinates = Transform(uid).Coordinates;
var helmet = Spawn("ClothingHeadHelmetCult", coordinates);
var armor = Spawn("ClothingOuterArmorCult", coordinates);
var shoes = Spawn("ClothingShoesCult", coordinates);
var blade = Spawn("EldritchBlade", coordinates);
var bola = Spawn("CultBola", coordinates);
_inventorySystem.TryUnequip(uid, "head");
_inventorySystem.TryUnequip(uid, "outerClothing");
_inventorySystem.TryUnequip(uid, "shoes");
_inventorySystem.TryEquip(uid, helmet, "head", force: true);
_inventorySystem.TryEquip(uid, armor, "outerClothing", force: true);
_inventorySystem.TryEquip(uid, shoes, "shoes", force: true);
_handsSystem.PickupOrDrop(uid, blade);
_handsSystem.PickupOrDrop(uid, bola);
args.Handled = true;
}
private void OnElectromagneticPulse(
EntityUid uid,
CultistComponent component,
CultElectromagneticPulseInstantActionEvent args)
{
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstream))
return;
_bloodstreamSystem.TryModifyBloodLevel(uid, -10, bloodstream, createPuddle: false);
_empSystem.EmpPulse(_transform.GetMapCoordinates(uid), 5, 100000, 10f);
args.Handled = true;
}
private void OnShadowShackles(EntityUid uid, CultistComponent component, CultShadowShacklesTargetActionEvent args)
{
if (args.Target == uid || !TryComp<BloodstreamComponent>(args.Performer, out var bloodstream))
return;
_bloodstreamSystem.TryModifyBloodLevel(uid, -5, bloodstream, createPuddle: false);
if (!_holyWeapon.IsHoldingHolyWeapon(args.Target) &&
_statusEffectsSystem.TryAddStatusEffect(args.Target, "Muted", TimeSpan.FromSeconds(10), true, "Muted"))
{
_popupSystem.PopupEntity("Цель обезмолвлена.", args.Performer, args.Performer);
args.Handled = true;
}
if (!TryComp(args.Target, out CuffableComponent? cuffs) || cuffs.Container.ContainedEntities.Count > 0)
return;
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.Performer, TimeSpan.FromSeconds(2),
new ShacklesEvent(), args.Performer, args.Target)
{
BreakOnMove = true,
BreakOnDamage = true
});
args.Handled = true;
}
private void OnTwistedConstructionAction(
EntityUid uid,
CultistComponent component,
CultTwistedConstructionActionEvent args)
{
if (args.Handled)
return;
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstreamComponent))
return;
if (!_entityManager.TryGetComponent<StackComponent>(args.Target, out var stack))
return;
if (stack.StackTypeId != SteelPrototypeId)
return;
var transform = Transform(args.Target).Coordinates;
var count = stack.Count;
_entityManager.DeleteEntity(args.Target);
var material = _entityManager.SpawnEntity(RunicMetalPrototypeId, transform);
_bloodstreamSystem.TryModifyBloodLevel(args.Performer, -stack.Count / 2f, bloodstreamComponent, false);
if (!_entityManager.TryGetComponent<StackComponent>(material, out var stackNew))
return;
stackNew.Count = count;
_popupSystem.PopupEntity("Конвертируем сталь в руинический металл!", args.Performer, args.Performer);
args.Handled = true;
}
private void OnSummonDaggerAction(EntityUid uid, CultistComponent component, CultSummonDaggerActionEvent args)
{
if (args.Handled)
return;
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstreamComponent))
return;
var xform = Transform(args.Performer).Coordinates;
var dagger = _entityManager.SpawnEntity(RitualDaggerPrototypeId, xform);
_bloodstreamSystem.TryModifyBloodLevel(args.Performer, -10, bloodstreamComponent, false);
_handsSystem.TryPickupAnyHand(args.Performer, dagger);
args.Handled = true;
}
}