Залью спеллы потестить, мне похуй ПР НОМЕР 156

* refactor CheZaHuetaMagicSystem

* эщкере

* alt-spells system. lmb, rmb, alt-click

* fix

* ChargeSpellsIndicator + Visual(CheZaHueta)

* Custom charge effect for spell

* Custom MaxChargeLevel

* Finally. Alt spells seems to work!! Need to start do spells and gamerule

* fuckkk

* fix crash, actually burn scroll..

* some fixes blyat

* ArcSpell

* очередная CheZaHuetaSystem, ForceSpell

* ONI'SOMA!

* mraow

* prepare this LMAO

* Yebanyy rot etogo kazino blyat! - CardsSpell

* forcewall

* nig

* blink

* Ethereal Jaunt

* игра говно

* Блядина

* ну на еще спеллов

* blyadina

* да иди ты нахуй БЛЯДЬ

* кто прочитал, тот сдохнет. сделай 5 репостов чтобы выжить....

* icons

* та ваще поебать

* одежда
This commit is contained in:
rhailrake
2024-03-07 16:01:54 +00:00
committed by GitHub
parent d944178a7b
commit c08cdeb84d
99 changed files with 3461 additions and 406 deletions

View File

@@ -1,17 +1,15 @@
using System.Linq;
using System.Numerics;
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Server.Chat.Systems;
using Content.Server.Doors.Systems;
using Content.Server.Magic.Components;
using Content.Server.Weapons.Ranged.Systems;
using Content.Shared.Actions;
using Content.Shared.Body.Components;
using Content.Shared.Coordinates.Helpers;
using Content.Shared.DoAfter;
using Content.Shared.Doors.Components;
using Content.Shared.Doors.Systems;
using Content.Shared.Interaction.Events;
using Content.Shared.Magic;
using Content.Shared.Magic.Events;
using Content.Shared.Maps;
@@ -21,6 +19,7 @@ using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Components;
using Robust.Shared.Random;
using Robust.Shared.Serialization.Manager;
@@ -33,31 +32,25 @@ namespace Content.Server.Magic;
/// </summary>
public sealed class MagicSystem : EntitySystem
{
[Dependency] private readonly ISerializationManager _seriMan = default!;
[Dependency] private readonly ISerializationManager _serializationManager = default!;
[Dependency] private readonly IComponentFactory _compFact = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly DoorBoltSystem _boltsSystem = default!;
[Dependency] private readonly BodySystem _bodySystem = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly SharedDoorSystem _doorSystem = default!;
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly GunSystem _gunSystem = default!;
[Dependency] private readonly PhysicsSystem _physics = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly ChatSystem _chat = default!;
[Dependency] private readonly ActionContainerSystem _actionContainer = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SpellbookComponent, MapInitEvent>(OnInit);
SubscribeLocalEvent<SpellbookComponent, UseInHandEvent>(OnUse);
SubscribeLocalEvent<SpellbookComponent, SpellbookDoAfterEvent>(OnDoAfter);
SubscribeLocalEvent<InstantSpawnSpellEvent>(OnInstantSpawn);
SubscribeLocalEvent<TeleportSpellEvent>(OnTeleportSpell);
SubscribeLocalEvent<KnockSpellEvent>(OnKnockSpell);
@@ -67,73 +60,8 @@ public sealed class MagicSystem : EntitySystem
SubscribeLocalEvent<ChangeComponentsSpellEvent>(OnChangeComponentsSpell);
}
private void OnDoAfter(EntityUid uid, SpellbookComponent component, DoAfterEvent args)
{
if (args.Handled || args.Cancelled)
return;
args.Handled = true;
if (!component.LearnPermanently)
{
_actionsSystem.GrantActions(args.Args.User, component.Spells, uid);
return;
}
foreach (var (id, charges) in component.SpellActions)
{
// TOOD store spells entity ids on some sort of innate magic user component or something like that.
EntityUid? actionId = null;
if (_actionsSystem.AddAction(args.Args.User, ref actionId, id))
_actionsSystem.SetCharges(actionId, charges < 0 ? null : charges);
}
component.SpellActions.Clear();
}
private void OnInit(EntityUid uid, SpellbookComponent component, MapInitEvent args)
{
if (component.LearnPermanently)
return;
foreach (var (id, charges) in component.SpellActions)
{
var spell = _actionContainer.AddAction(uid, id);
if (spell == null)
continue;
_actionsSystem.SetCharges(spell, charges < 0 ? null : charges);
component.Spells.Add(spell.Value);
}
}
private void OnUse(EntityUid uid, SpellbookComponent component, UseInHandEvent args)
{
if (args.Handled)
return;
AttemptLearn(uid, component, args);
args.Handled = true;
}
private void AttemptLearn(EntityUid uid, SpellbookComponent component, UseInHandEvent args)
{
var doAfterEventArgs = new DoAfterArgs(EntityManager, args.User, component.LearnTime, new SpellbookDoAfterEvent(), uid, target: uid)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
BreakOnDamage = true,
NeedHand = true //What, are you going to read with your eyes only??
};
_doAfter.TryStartDoAfter(doAfterEventArgs);
}
#region Spells
/// <summary>
/// Handles the instant action (i.e. on the caster) attempting to spawn an entity.
/// </summary>
private void OnInstantSpawn(InstantSpawnSpellEvent args)
{
if (args.Handled)
@@ -145,11 +73,11 @@ public sealed class MagicSystem : EntitySystem
{
var ent = Spawn(args.Prototype, position.SnapToGrid(EntityManager, _mapManager));
if (args.PreventCollideWithCaster)
{
var comp = EnsureComp<PreventCollideComponent>(ent);
comp.Uid = args.Performer;
}
if (!args.PreventCollideWithCaster)
continue;
var comp = EnsureComp<PreventCollideComponent>(ent);
comp.Uid = args.Performer;
}
Speak(args);
@@ -166,22 +94,17 @@ public sealed class MagicSystem : EntitySystem
var xform = Transform(ev.Performer);
// var userVelocity = _physics.GetMapLinearVelocity(ev.Performer); WD EDIT
foreach (var pos in GetSpawnPositions(xform, ev.Pos))
{
// If applicable, this ensures the projectile is parented to grid on spawn, instead of the map.
var mapPos = pos.ToMap(EntityManager);
var spawnCoords = _mapManager.TryFindGridAt(mapPos, out var gridUid, out var grid) // WD EDIT
var mapPos = _transformSystem.ToMapCoordinates(pos);
var spawnCoords = _mapManager.TryFindGridAt(mapPos, out var gridUid, out var grid)
? pos.WithEntityId(gridUid, EntityManager)
: new(_mapManager.GetMapEntityId(mapPos.MapId), mapPos.Position);
: new EntityCoordinates(_mapManager.GetMapEntityId(mapPos.MapId), mapPos.Position);
// WD EDIT
var userVelocity = Vector2.Zero;
if (grid != null && TryComp(gridUid, out PhysicsComponent? physics))
userVelocity = physics.LinearVelocity;
// WD EDIT
var ent = Spawn(ev.Prototype, spawnCoords);
var direction = ev.Target.ToMapPos(EntityManager, _transformSystem) -
@@ -194,7 +117,9 @@ public sealed class MagicSystem : EntitySystem
{
if (ev.Handled)
return;
ev.Handled = true;
Speak(ev);
foreach (var toRemove in ev.ToRemove)
@@ -209,75 +134,12 @@ public sealed class MagicSystem : EntitySystem
continue;
var component = (Component) _compFact.GetComponent(name);
component.Owner = ev.Target;
var temp = (object) component;
_seriMan.CopyTo(data.Component, ref temp);
_serializationManager.CopyTo(data.Component, ref temp);
EntityManager.AddComponent(ev.Target, (Component) temp!);
}
}
private List<EntityCoordinates> GetSpawnPositions(TransformComponent casterXform, MagicSpawnData data)
{
switch (data)
{
case TargetCasterPos:
return new List<EntityCoordinates>(1) {casterXform.Coordinates};
case TargetInFront:
{
// This is shit but you get the idea.
var directionPos = casterXform.Coordinates.Offset(casterXform.LocalRotation.ToWorldVec().Normalized());
if (!_mapManager.TryGetGrid(casterXform.GridUid, out var mapGrid))
return new List<EntityCoordinates>();
if (!directionPos.TryGetTileRef(out var tileReference, EntityManager, _mapManager))
return new List<EntityCoordinates>();
var tileIndex = tileReference.Value.GridIndices;
var coords = mapGrid.GridTileToLocal(tileIndex);
EntityCoordinates coordsPlus;
EntityCoordinates coordsMinus;
var dir = casterXform.LocalRotation.GetCardinalDir();
switch (dir)
{
case Direction.North:
case Direction.South:
{
coordsPlus = mapGrid.GridTileToLocal(tileIndex + (1, 0));
coordsMinus = mapGrid.GridTileToLocal(tileIndex + (-1, 0));
return new List<EntityCoordinates>(3)
{
coords,
coordsPlus,
coordsMinus,
};
}
case Direction.East:
case Direction.West:
{
coordsPlus = mapGrid.GridTileToLocal(tileIndex + (0, 1));
coordsMinus = mapGrid.GridTileToLocal(tileIndex + (0, -1));
return new List<EntityCoordinates>(3)
{
coords,
coordsPlus,
coordsMinus,
};
}
}
return new List<EntityCoordinates>();
}
default:
throw new ArgumentOutOfRangeException();
}
}
/// <summary>
/// Teleports the user to the clicked location
/// </summary>
/// <param name="args"></param>
private void OnTeleportSpell(TeleportSpellEvent args)
{
if (args.Handled)
@@ -285,19 +147,16 @@ public sealed class MagicSystem : EntitySystem
var transform = Transform(args.Performer);
if (transform.MapID != args.Target.GetMapId(EntityManager)) return;
if (transform.MapID != args.Target.GetMapId(EntityManager))
return;
_transformSystem.SetCoordinates(args.Performer, args.Target);
transform.AttachToGridOrMap();
_transformSystem.AttachToGridOrMap(args.Performer);
_audio.PlayPvs(args.BlinkSound, args.Performer, AudioParams.Default.WithVolume(args.BlinkVolume));
Speak(args);
args.Handled = true;
}
/// <summary>
/// Opens all doors within range
/// </summary>
/// <param name="args"></param>
private void OnKnockSpell(KnockSpellEvent args)
{
if (args.Handled)
@@ -306,13 +165,11 @@ public sealed class MagicSystem : EntitySystem
args.Handled = true;
Speak(args);
//Get the position of the player
var transform = Transform(args.Performer);
var coords = transform.Coordinates;
_audio.PlayPvs(args.KnockSound, args.Performer, AudioParams.Default.WithVolume(args.KnockVolume));
//Look for doors and don't open them if they're already open.
foreach (var entity in _lookup.GetEntitiesInRange(coords, args.Range))
{
if (TryComp<DoorBoltComponent>(entity, out var bolts))
@@ -329,9 +186,10 @@ public sealed class MagicSystem : EntitySystem
return;
ev.Handled = true;
Speak(ev);
var direction = Transform(ev.Target).MapPosition.Position - Transform(ev.Performer).MapPosition.Position;
var direction = _transformSystem.GetMapCoordinates(ev.Target).Position - _transformSystem.GetMapCoordinates(ev.Performer).Position;
var impulseVector = direction * 10000;
_physics.ApplyLinearImpulse(ev.Target, impulseVector);
@@ -339,28 +197,17 @@ public sealed class MagicSystem : EntitySystem
if (!TryComp<BodyComponent>(ev.Target, out var body))
return;
var ents = _bodySystem.GibBody(ev.Target, true, body);
var entities = _bodySystem.GibBody(ev.Target, true, body);
if (!ev.DeleteNonBrainParts)
return;
foreach (var part in ents)
foreach (var part in entities.Where(part => HasComp<BodyComponent>(part) && !HasComp<BrainComponent>(part)))
{
// just leaves a brain and clothes
if (HasComp<BodyComponent>(part) && !HasComp<BrainComponent>(part))
{
QueueDel(part);
}
QueueDel(part);
}
}
/// <summary>
/// Spawns entity prototypes from a list within range of click.
/// </summary>
/// <remarks>
/// It will offset mobs after the first mob based on the OffsetVector2 property supplied.
/// </remarks>
/// <param name="args"> The Spawn Spell Event args.</param>
private void OnWorldSpawn(WorldSpawnSpellEvent args)
{
if (args.Handled)
@@ -373,24 +220,85 @@ public sealed class MagicSystem : EntitySystem
args.Handled = true;
}
/// <summary>
/// Loops through a supplied list of entity prototypes and spawns them
/// </summary>
/// <remarks>
/// If an offset of 0, 0 is supplied then the entities will all spawn on the same tile.
/// Any other offset will spawn entities starting from the source Map Coordinates and will increment the supplied
/// offset
/// </remarks>
/// <param name="entityEntries"> The list of Entities to spawn in</param>
/// <param name="entityCoords"> Map Coordinates where the entities will spawn</param>
/// <param name="lifetime"> Check to see if the entities should self delete</param>
/// <param name="offsetVector2"> A Vector2 offset that the entities will spawn in</param>
private void SpawnSpellHelper(List<EntitySpawnEntry> entityEntries, EntityCoordinates entityCoords, float? lifetime, Vector2 offsetVector2)
#endregion
#region Helpers
public List<EntityCoordinates> GetSpawnPositions(TransformComponent casterXform, MagicSpawnData data)
{
var getProtos = EntitySpawnCollection.GetSpawns(entityEntries, _random);
return data switch
{
TargetCasterPos => GetCasterPosition(casterXform),
TargetInFront => GetPositionsInFront(casterXform),
_ => throw new ArgumentOutOfRangeException()
};
}
public List<EntityCoordinates> GetCasterPosition(TransformComponent casterXform)
{
return new List<EntityCoordinates>(1) { casterXform.Coordinates };
}
public List<EntityCoordinates> GetPositionsInFront(TransformComponent casterXform)
{
var directionPos = casterXform.Coordinates.Offset(casterXform.LocalRotation.ToWorldVec().Normalized());
if (!TryComp<MapGridComponent>(casterXform.GridUid, out var mapGrid) ||
!directionPos.TryGetTileRef(out var tileReference, EntityManager, _mapManager))
{
return new List<EntityCoordinates>();
}
var tileIndex = tileReference.Value.GridIndices;
var coords = _mapSystem.GridTileToLocal(casterXform.GridUid.Value, mapGrid, tileIndex);
var directions = GetCardinalDirections(casterXform.LocalRotation.GetCardinalDir());
var spawnPositions = new List<EntityCoordinates>(3);
foreach (var direction in directions)
{
var offset = GetOffsetForDirection(direction);
var coordinates = _mapSystem.GridTileToLocal(casterXform.GridUid.Value, mapGrid, tileIndex + offset);
spawnPositions.Add(coordinates);
}
spawnPositions.Add(coords);
return spawnPositions;
}
public IEnumerable<Direction> GetCardinalDirections(Direction dir)
{
switch (dir)
{
case Direction.North:
case Direction.South:
return new[] { Direction.North, Direction.South };
case Direction.East:
case Direction.West:
return new[] { Direction.East, Direction.West };
default:
return Array.Empty<Direction>();
}
}
public (int, int) GetOffsetForDirection(Direction direction)
{
return direction switch
{
Direction.North => (1, 0),
Direction.South => (-1, 0),
Direction.East => (0, 1),
Direction.West => (0, -1),
_ => (0, 0)
};
}
public void SpawnSpellHelper(List<EntitySpawnEntry> entityEntries, EntityCoordinates entityCoords, float? lifetime, Vector2 offsetVector2)
{
var getPrototypes = EntitySpawnCollection.GetSpawns(entityEntries, _random);
var offsetCoords = entityCoords;
foreach (var proto in getProtos)
foreach (var proto in getPrototypes)
{
// TODO: Share this code with instant because they're both doing similar things for positioning.
var entity = Spawn(proto, offsetCoords);
@@ -404,8 +312,6 @@ public sealed class MagicSystem : EntitySystem
}
}
#endregion
private void Speak(BaseActionEvent args)
{
if (args is not ISpeakSpell speak || string.IsNullOrWhiteSpace(speak.Speech))
@@ -414,4 +320,6 @@ public sealed class MagicSystem : EntitySystem
_chat.TrySendInGameICMessage(args.Performer, Loc.GetString(speak.Speech),
InGameICChatType.Speak, false);
}
#endregion
}