Magic 8 (#376)
* - add: Flash protection for wiz hardsuit helmet. * - tweak: Cheaper wiz melee weapons. * - add: Rework alt lightning. * - fix: Timestop fixes. * - add: Don't end round on midround wizard death. * - tweak: Better shield. * - fix: Some fixes. * - fix: Fix wizard teleport pulling. * - add: Improve arc. * - add: Update knock. * - add: Update knock desc. * - add: Arcane Barrage.
This commit is contained in:
@@ -205,7 +205,8 @@ public sealed partial class ExplosionSystem
|
||||
MapCoordinates epicenter,
|
||||
HashSet<EntityUid> processed,
|
||||
string id,
|
||||
float? fireStacks)
|
||||
float? fireStacks,
|
||||
bool ignoreResistances) // WD
|
||||
{
|
||||
var size = grid.Comp.TileSize;
|
||||
var gridBox = new Box2(tile * size, (tile + 1) * size);
|
||||
@@ -224,7 +225,7 @@ public sealed partial class ExplosionSystem
|
||||
// process those entities
|
||||
foreach (var (uid, xform) in list)
|
||||
{
|
||||
ProcessEntity(uid, epicenter, damage, throwForce, id, xform, fireStacks);
|
||||
ProcessEntity(uid, epicenter, damage, throwForce, id, xform, fireStacks, ignoreResistances); // WD EDIT
|
||||
}
|
||||
|
||||
// process anchored entities
|
||||
@@ -234,7 +235,7 @@ public sealed partial class ExplosionSystem
|
||||
foreach (var entity in _anchored)
|
||||
{
|
||||
processed.Add(entity);
|
||||
ProcessEntity(entity, epicenter, damage, throwForce, id, null, fireStacks);
|
||||
ProcessEntity(entity, epicenter, damage, throwForce, id, null, fireStacks, ignoreResistances); // WD EDIT
|
||||
}
|
||||
|
||||
// Walls and reinforced walls will break into girders. These girders will also be considered turf-blocking for
|
||||
@@ -270,7 +271,7 @@ public sealed partial class ExplosionSystem
|
||||
{
|
||||
// Here we only throw, no dealing damage. Containers n such might drop their entities after being destroyed, but
|
||||
// they should handle their own damage pass-through, with their own damage reduction calculation.
|
||||
ProcessEntity(uid, epicenter, null, throwForce, id, xform, null);
|
||||
ProcessEntity(uid, epicenter, null, throwForce, id, xform, null, ignoreResistances); // WD EDIT
|
||||
}
|
||||
|
||||
return !tileBlocked;
|
||||
@@ -306,7 +307,8 @@ public sealed partial class ExplosionSystem
|
||||
MapCoordinates epicenter,
|
||||
HashSet<EntityUid> processed,
|
||||
string id,
|
||||
float? fireStacks)
|
||||
float? fireStacks,
|
||||
bool ignoreResistances) // WD
|
||||
{
|
||||
var gridBox = Box2.FromDimensions(tile * DefaultTileSize, new Vector2(DefaultTileSize, DefaultTileSize));
|
||||
var worldBox = spaceMatrix.TransformBox(gridBox);
|
||||
@@ -322,7 +324,7 @@ public sealed partial class ExplosionSystem
|
||||
foreach (var (uid, xform) in state.Item1)
|
||||
{
|
||||
processed.Add(uid);
|
||||
ProcessEntity(uid, epicenter, damage, throwForce, id, xform, fireStacks);
|
||||
ProcessEntity(uid, epicenter, damage, throwForce, id, xform, fireStacks, ignoreResistances);
|
||||
}
|
||||
|
||||
if (throwForce <= 0)
|
||||
@@ -336,7 +338,7 @@ public sealed partial class ExplosionSystem
|
||||
|
||||
foreach (var (uid, xform) in list)
|
||||
{
|
||||
ProcessEntity(uid, epicenter, null, throwForce, id, xform, fireStacks);
|
||||
ProcessEntity(uid, epicenter, null, throwForce, id, xform, fireStacks, ignoreResistances);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,7 +436,8 @@ public sealed partial class ExplosionSystem
|
||||
float throwForce,
|
||||
string id,
|
||||
TransformComponent? xform,
|
||||
float? fireStacksOnIgnite)
|
||||
float? fireStacksOnIgnite,
|
||||
bool ignoreResistances) // WD
|
||||
{
|
||||
if (originalDamage != null)
|
||||
{
|
||||
@@ -442,7 +445,7 @@ public sealed partial class ExplosionSystem
|
||||
foreach (var (entity, damage) in _toDamage)
|
||||
{
|
||||
// TODO EXPLOSIONS turn explosions into entities, and pass the the entity in as the damage origin.
|
||||
_damageableSystem.TryChangeDamage(entity, damage, ignoreResistances: true);
|
||||
_damageableSystem.TryChangeDamage(entity, damage, ignoreResistances: ignoreResistances); // WD EDIT
|
||||
|
||||
}
|
||||
}
|
||||
@@ -827,7 +830,8 @@ sealed class Explosion
|
||||
Epicenter,
|
||||
ProcessedEntities,
|
||||
ExplosionType.ID,
|
||||
ExplosionType.FireStacks);
|
||||
ExplosionType.FireStacks,
|
||||
ExplosionType.IgnoreResistances); // WD
|
||||
|
||||
// If the floor is not blocked by some dense object, damage the floor tiles.
|
||||
if (canDamageFloor)
|
||||
@@ -845,7 +849,8 @@ sealed class Explosion
|
||||
Epicenter,
|
||||
ProcessedEntities,
|
||||
ExplosionType.ID,
|
||||
ExplosionType.FireStacks);
|
||||
ExplosionType.FireStacks,
|
||||
ExplosionType.IgnoreResistances); // WD
|
||||
}
|
||||
|
||||
if (!MoveNext())
|
||||
|
||||
@@ -10,6 +10,7 @@ using Content.Shared.Body.Components;
|
||||
using Content.Shared.Coordinates.Helpers;
|
||||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Doors.Systems;
|
||||
using Content.Shared.Lock;
|
||||
using Content.Shared.Magic;
|
||||
using Content.Shared.Magic.Events;
|
||||
using Content.Shared.Maps;
|
||||
@@ -46,6 +47,7 @@ public sealed class MagicSystem : EntitySystem
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly ChatSystem _chat = default!;
|
||||
[Dependency] private readonly WizardSpellsSystem _wizardSpells = default!;
|
||||
[Dependency] private readonly LockSystem _lock = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -177,6 +179,9 @@ public sealed class MagicSystem : EntitySystem
|
||||
|
||||
if (TryComp<DoorComponent>(entity, out var doorComp) && doorComp.State is not DoorState.Open)
|
||||
_doorSystem.StartOpening(entity);
|
||||
|
||||
if (TryComp<LockComponent>(entity, out var lockComp) && lockComp.Locked)
|
||||
_lock.Unlock(entity, null, lockComp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace Content.Server._White.Wizard.GravPulseOnStartup;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class GravPulseOnStartupComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public float MaxRange;
|
||||
|
||||
[DataField]
|
||||
public float MinRange;
|
||||
|
||||
[DataField]
|
||||
public float BaseRadialAcceleration;
|
||||
|
||||
[DataField]
|
||||
public float BaseTangentialAcceleration;
|
||||
|
||||
[DataField]
|
||||
public float StunTime;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Content.Server.Singularity.EntitySystems;
|
||||
|
||||
namespace Content.Server._White.Wizard.GravPulseOnStartup;
|
||||
|
||||
public sealed class GravPulseOnStartupSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly GravityWellSystem _gravityWell = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<GravPulseOnStartupComponent, ComponentStartup>(OnStartup);
|
||||
}
|
||||
|
||||
private void OnStartup(Entity<GravPulseOnStartupComponent> ent, ref ComponentStartup args)
|
||||
{
|
||||
var (uid, comp) = ent;
|
||||
_gravityWell.GravPulse(Transform(uid).Coordinates, comp.MaxRange, comp.MinRange, comp.BaseRadialAcceleration,
|
||||
comp.BaseTangentialAcceleration, comp.StunTime);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
namespace Content.Server._White.Wizard.Magic.TeslaProjectile;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class TeslaProjectileComponent : Component {}
|
||||
public sealed partial class TeslaProjectileComponent : Component
|
||||
{
|
||||
[ViewVariables]
|
||||
public EntityUid? Caster;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ public sealed class TeslaProjectileSystem : EntitySystem
|
||||
|
||||
private void OnStartCollide(Entity<TeslaProjectileComponent> ent, ref ProjectileHitEvent args)
|
||||
{
|
||||
_lightning.ShootRandomLightnings(ent, 2, 4, arcDepth:2);
|
||||
_lightning.ShootRandomLightnings(ent, 3, 4, "WizardLightning", 2, false, ent.Comp.Caster);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using Content.Server._White.Cult;
|
||||
using Content.Server._White.IncorporealSystem;
|
||||
using Content.Server._White.Wizard.Magic.Amaterasu;
|
||||
using Content.Server._White.Wizard.Magic.Other;
|
||||
using Content.Server._White.Wizard.Magic.TeslaProjectile;
|
||||
using Content.Server._White.Wizard.Teleport;
|
||||
using Content.Server.Abilities.Mime;
|
||||
using Content.Server.Administration.Commands;
|
||||
@@ -86,6 +87,7 @@ public sealed class WizardSpellsSystem : EntitySystem
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ArcaneBarrageSpellEvent>(OnArcaneBarrage);
|
||||
SubscribeLocalEvent<StopTimeSpellEvent>(OnTimeStop);
|
||||
SubscribeLocalEvent<MindswapSpellEvent>(OnMindswapSpell);
|
||||
SubscribeLocalEvent<TeleportSpellEvent>(OnTeleportSpell);
|
||||
@@ -105,6 +107,29 @@ public sealed class WizardSpellsSystem : EntitySystem
|
||||
SubscribeLocalEvent<MagicComponent, BeforeCastSpellEvent>(OnBeforeCastSpell);
|
||||
}
|
||||
|
||||
#region Arcane Barrage
|
||||
|
||||
private void OnArcaneBarrage(ArcaneBarrageSpellEvent msg)
|
||||
{
|
||||
if (!CanCast(msg))
|
||||
return;
|
||||
|
||||
var uid = msg.Performer;
|
||||
|
||||
var entity = Spawn(msg.Prototype, Transform(uid).Coordinates);
|
||||
if (!_handsSystem.TryPickupAnyHand(uid, entity))
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("arcane-barrage-no-empty-hand"), uid, uid);
|
||||
QueueDel(entity);
|
||||
_actions.SetCooldown(msg.Action, TimeSpan.FromSeconds(1));
|
||||
return;
|
||||
}
|
||||
|
||||
msg.Handled = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Timestop
|
||||
|
||||
private void OnTimeStop(StopTimeSpellEvent msg)
|
||||
@@ -803,6 +828,7 @@ public sealed class WizardSpellsSystem : EntitySystem
|
||||
userVelocity = physics.LinearVelocity;
|
||||
|
||||
var ent = Spawn(msg.Prototype, spawnCoords);
|
||||
EnsureComp<TeslaProjectileComponent>(ent).Caster = msg.Performer;
|
||||
var direction = msg.Target.ToMapPos(EntityManager, _transformSystem) -
|
||||
spawnCoords.ToMapPos(EntityManager, _transformSystem);
|
||||
_gunSystem.ShootProjectile(ent, direction, userVelocity, msg.Performer, msg.Performer);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared._White.Wizard.Teleport;
|
||||
using Content.Shared.Eui;
|
||||
using Content.Shared.Movement.Pulling.Components;
|
||||
using Content.Shared.Movement.Pulling.Systems;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server._White.Wizard.Teleport;
|
||||
@@ -11,6 +13,7 @@ public sealed class WizardTeleportSpellEui : BaseEui
|
||||
[Dependency] private readonly EntityManager _entityManager = default!;
|
||||
private readonly SharedTransformSystem _transformSystem;
|
||||
private readonly TeleportLocationSystem _teleportLocation;
|
||||
private readonly PullingSystem _pulling;
|
||||
private readonly PopupSystem _popupSystem;
|
||||
|
||||
private readonly EntityUid _performer;
|
||||
@@ -22,6 +25,7 @@ public sealed class WizardTeleportSpellEui : BaseEui
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_transformSystem = _entityManager.System<SharedTransformSystem>();
|
||||
_pulling = _entityManager.System<PullingSystem>();
|
||||
_teleportLocation = _entityManager.System<TeleportLocationSystem>();
|
||||
_popupSystem = _entityManager.System<PopupSystem>();
|
||||
|
||||
@@ -82,6 +86,19 @@ public sealed class WizardTeleportSpellEui : BaseEui
|
||||
|
||||
_used = true;
|
||||
|
||||
// break pulls before portal enter so we dont break shit
|
||||
if (_entityManager.TryGetComponent<PullableComponent>(_performer, out var pullable) && pullable.BeingPulled)
|
||||
{
|
||||
_pulling.TryStopPull(_performer, pullable);
|
||||
}
|
||||
|
||||
if (_entityManager.TryGetComponent<PullerComponent>(_performer, out var pulling)
|
||||
&& pulling.Pulling != null
|
||||
&& _entityManager.TryGetComponent<PullableComponent>(pulling.Pulling.Value, out var subjectPulling))
|
||||
{
|
||||
_pulling.TryStopPull(pulling.Pulling.Value, subjectPulling);
|
||||
}
|
||||
|
||||
var coords = locationTransform.Coordinates;
|
||||
|
||||
_transformSystem.SetCoordinates(_performer, coords);
|
||||
|
||||
@@ -4,4 +4,6 @@ namespace Content.Server._White.Wizard;
|
||||
[RegisterComponent]
|
||||
public sealed partial class WizardComponent : Component
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool EndRoundOnDeath;
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ public sealed class WizardRuleSystem : GameRuleSystem<WizardRuleComponent>
|
||||
|
||||
private void OnMobStateChanged(EntityUid uid, WizardComponent component, MobStateChangedEvent ev)
|
||||
{
|
||||
if (ev.NewMobState == MobState.Dead)
|
||||
if (ev.NewMobState == MobState.Dead && component.EndRoundOnDeath)
|
||||
CheckAnnouncement();
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public sealed class WizardRuleSystem : GameRuleSystem<WizardRuleComponent>
|
||||
return;
|
||||
}
|
||||
|
||||
SetupWizardEntity(uid, wizardSpawner.Points, gear, profile);
|
||||
SetupWizardEntity(uid, gear, profile, false);
|
||||
}
|
||||
|
||||
private void OnMindAdded(EntityUid uid, WizardComponent component, MindAddedMessage args)
|
||||
@@ -280,11 +280,11 @@ public sealed class WizardRuleSystem : GameRuleSystem<WizardRuleComponent>
|
||||
|
||||
private void SetupWizardEntity(
|
||||
EntityUid mob,
|
||||
int points,
|
||||
StartingGearPrototype gear,
|
||||
HumanoidCharacterProfile? profile)
|
||||
HumanoidCharacterProfile? profile,
|
||||
bool endRoundOnDeath)
|
||||
{
|
||||
EnsureComp<WizardComponent>(mob);
|
||||
EnsureComp<WizardComponent>(mob).EndRoundOnDeath = endRoundOnDeath;
|
||||
|
||||
profile ??= HumanoidCharacterProfile.RandomWithSpecies();
|
||||
|
||||
@@ -346,7 +346,7 @@ public sealed class WizardRuleSystem : GameRuleSystem<WizardRuleComponent>
|
||||
return;
|
||||
}
|
||||
|
||||
SetupWizardEntity(mob, component.Points, gear, profile);
|
||||
SetupWizardEntity(mob, gear, profile, true);
|
||||
|
||||
var newMind = _mind.CreateMind(session.UserId, name);
|
||||
_mind.SetUserId(newMind, session.UserId);
|
||||
|
||||
@@ -10,9 +10,6 @@ public sealed partial class WizardSpawnerComponent : Component
|
||||
[DataField("name")]
|
||||
public string Name = "Ololo The Balls' Twister";
|
||||
|
||||
[DataField("points")]
|
||||
public int Points = 10;
|
||||
|
||||
[DataField("startingGear")]
|
||||
public ProtoId<StartingGearPrototype> StartingGear = "WizardGear";
|
||||
|
||||
|
||||
@@ -110,6 +110,11 @@ public sealed partial class ExplosionPrototype : IPrototype
|
||||
[DataField("fireStates")]
|
||||
public int FireStates = 3;
|
||||
|
||||
// WD START
|
||||
[DataField]
|
||||
public bool IgnoreResistances = true;
|
||||
// WD END
|
||||
|
||||
/// <summary>
|
||||
/// Basic function for linear interpolation of the _tileBreakChance and _tileBreakIntensity arrays
|
||||
/// </summary>
|
||||
|
||||
@@ -540,6 +540,10 @@ public abstract partial class SharedGunSystem : EntitySystem
|
||||
gun.UseKey = useKey;
|
||||
}
|
||||
|
||||
public void SetClumsyProof(GunComponent gun, bool clumsyProof)
|
||||
{
|
||||
gun.ClumsyProof = clumsyProof;
|
||||
}
|
||||
public void SetProjectileSpeed(EntityUid weapon, float projectileSpeed)
|
||||
{
|
||||
if(!TryComp<GunComponent>(weapon, out var gunComponent))
|
||||
|
||||
@@ -27,7 +27,7 @@ public sealed class BoltBarrageSystem : EntitySystem
|
||||
SubscribeLocalEvent<BoltBarrageComponent, AttemptShootEvent>(OnShootAttempt);
|
||||
SubscribeLocalEvent<BoltBarrageComponent, GunShotEvent>(OnGunShot);
|
||||
SubscribeLocalEvent<BoltBarrageComponent, DroppedEvent>(OnDrop);
|
||||
SubscribeLocalEvent<BoltBarrageComponent, UnequippedHandEvent>(OnUnequipHand);
|
||||
SubscribeLocalEvent<BoltBarrageComponent, GotUnequippedHandEvent>(OnUnequipHand);
|
||||
SubscribeLocalEvent<BoltBarrageComponent, ContainerGettingRemovedAttemptEvent>(OnRemoveAttempt);
|
||||
SubscribeLocalEvent<BoltBarrageComponent, OnEmptyGunShotEvent>(OnEmptyShot);
|
||||
SubscribeLocalEvent<BoltBarrageComponent, ExaminedEvent>(OnExamine);
|
||||
@@ -38,7 +38,7 @@ public sealed class BoltBarrageSystem : EntitySystem
|
||||
args.PushMarkup(Loc.GetString("bolt-barrage-component-extra-desc"));
|
||||
}
|
||||
|
||||
private void OnUnequipHand(Entity<BoltBarrageComponent> ent, ref UnequippedHandEvent args)
|
||||
private void OnUnequipHand(Entity<BoltBarrageComponent> ent, ref GotUnequippedHandEvent args)
|
||||
{
|
||||
if (_net.IsServer && ent.Comp.Unremoveable)
|
||||
QueueDel(ent);
|
||||
@@ -82,12 +82,12 @@ public sealed class BoltBarrageSystem : EntitySystem
|
||||
|
||||
private void OnShootAttempt(Entity<BoltBarrageComponent> ent, ref AttemptShootEvent args)
|
||||
{
|
||||
if (!HasComp<CultistComponent>(args.User) && !HasComp<GhostComponent>(args.User))
|
||||
/*if (!HasComp<CultistComponent>(args.User) && !HasComp<GhostComponent>(args.User))
|
||||
{
|
||||
args.Cancelled = true;
|
||||
args.Message = Loc.GetString("bolt-barrage-component-not-cultist");
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (_hands.EnumerateHands(args.User).Any(hand => hand.IsEmpty))
|
||||
return;
|
||||
|
||||
@@ -102,6 +102,7 @@ public abstract class SharedSpellBladeSystem : EntitySystem
|
||||
{
|
||||
var gun = EnsureComp<GunComponent>(uid);
|
||||
_gun.SetUseKey(gun, false);
|
||||
_gun.SetClumsyProof(gun, true);
|
||||
_gun.SetSound(uid, new SoundPathSpecifier("/Audio/Weapons/Guns/Gunshots/Magic/staff_healing.ogg"));
|
||||
_gun.SetFireRate(uid, 1.2f);
|
||||
var ammoProvider = EnsureComp<BasicEntityAmmoProviderComponent>(uid);
|
||||
|
||||
@@ -8,6 +8,7 @@ using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Movement.Events;
|
||||
using Content.Shared.Speech;
|
||||
using Content.Shared.Standing.Systems;
|
||||
using Content.Shared.Throwing;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Physics;
|
||||
@@ -30,11 +31,14 @@ public sealed class FreezeContactsSystem : EntitySystem
|
||||
|
||||
SubscribeLocalEvent<FreezeContactsComponent, StartCollideEvent>(OnEntityEnter);
|
||||
SubscribeLocalEvent<FreezeContactsComponent, EndCollideEvent>(OnEntityExit);
|
||||
|
||||
SubscribeLocalEvent<FrozenComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<FrozenComponent, ComponentRemove>(OnRemove);
|
||||
SubscribeLocalEvent<FrozenComponent, PreventCollideEvent>(OnPreventCollide);
|
||||
SubscribeLocalEvent<FrozenComponent, EntGotInsertedIntoContainerMessage>(OnGetInserted);
|
||||
|
||||
SubscribeLocalEvent<FrozenComponent, StandAttemptEvent>(OnAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, DownAttemptEvent>(OnAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, SpeakAttemptEvent>(OnAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, EmoteAttemptEvent>(OnAttempt);
|
||||
SubscribeLocalEvent<FrozenComponent, ChangeDirectionAttemptEvent>(OnAttempt);
|
||||
@@ -152,21 +156,25 @@ public sealed class FreezeContactsSystem : EntitySystem
|
||||
|
||||
private void OnEntityEnter(Entity<FreezeContactsComponent> ent, ref StartCollideEvent args)
|
||||
{
|
||||
var hadFrozen = HasComp<FrozenComponent>(args.OtherEntity);
|
||||
var frozen = EnsureComp<FrozenComponent>(args.OtherEntity);
|
||||
FreezeEm(args.OtherEntity, ent);
|
||||
}
|
||||
|
||||
if (!TryComp(ent, out TimedDespawnComponent? timedDespawn))
|
||||
private void FreezeEm(EntityUid uid, EntityUid freezeContact)
|
||||
{
|
||||
if (HasComp<FrozenComponent>(uid))
|
||||
return;
|
||||
|
||||
var frozen = EnsureComp<FrozenComponent>(uid);
|
||||
|
||||
if (!TryComp(freezeContact, out TimedDespawnComponent? timedDespawn))
|
||||
return;
|
||||
|
||||
frozen.Lifetime = timedDespawn.Lifetime;
|
||||
|
||||
if (TryComp(args.OtherEntity, out TimedDespawnComponent? otherTimedDespawn))
|
||||
if (TryComp(uid, out TimedDespawnComponent? otherTimedDespawn))
|
||||
otherTimedDespawn.Lifetime += timedDespawn.Lifetime;
|
||||
|
||||
if (hadFrozen)
|
||||
return;
|
||||
|
||||
if (!TryComp(args.OtherEntity, out ThrownItemComponent? thrownItem))
|
||||
if (!TryComp(uid, out ThrownItemComponent? thrownItem))
|
||||
return;
|
||||
|
||||
if (thrownItem.LandTime != null)
|
||||
|
||||
@@ -193,4 +193,13 @@ public sealed partial class StopTimeSpellEvent : InstantActionEvent, ISpeakSpell
|
||||
public string? Speech { get; private set; }
|
||||
}
|
||||
|
||||
public sealed partial class ArcaneBarrageSpellEvent : InstantActionEvent, ISpeakSpell
|
||||
{
|
||||
[DataField("prototype", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string Prototype = default!;
|
||||
|
||||
[DataField("speech")]
|
||||
public string? Speech { get; private set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -18,6 +18,7 @@ scroll-component-teleport = телепортацию
|
||||
scroll-component-smite = кару
|
||||
scroll-component-mindswap = подмену сознания
|
||||
scroll-component-timestop = остановку времени
|
||||
scroll-component-barrage = магический залп
|
||||
|
||||
ent-BaseScroll = магический свиток
|
||||
.desc = Этот древний пергамент, ставший реликвией в арканных преданиях, хранит в себе бесчисленные мистические заклятия и забытые заклинания.
|
||||
@@ -55,3 +56,5 @@ ent-ScrollMindswap = свиток подмены сознания
|
||||
.desc = { ent-BaseScroll.desc }
|
||||
ent-ScrollTimestop = свиток остановки времени
|
||||
.desc = { ent-BaseScroll.desc }
|
||||
ent-ScrollArcaneBarrage = свиток магического залпа
|
||||
.desc = { ent-BaseScroll.desc }
|
||||
|
||||
@@ -46,6 +46,9 @@ spellbook-mindswap-desc = { ent-ActionMindswapSpell.desc }
|
||||
spellbook-timestop-name = { ent-ActionTimestopSpell }
|
||||
spellbook-timestop-desc = { ent-ActionTimestopSpell.desc }
|
||||
|
||||
spellbook-barrage-name = { ent-ActionArcaneBarrageSpell }
|
||||
spellbook-barrage-desc = { ent-ActionArcaneBarrageSpell.desc }
|
||||
|
||||
spellbook-hardsuit-name = Скафандр волшебника
|
||||
spellbook-hardsuit-desc = Украшенный магическими драгоценными камнями скафандр, функционирующий так же, как и обычная мантия волшебника, но в то же время является пригодным для использования в космосе и бронированным. Небольшое замедление. Теперь вы можете произносить заклинания в космосе и местах с низкой температурой! Имеет функцию энергетического щита,который защищает от всех снарядов. Щит разряжается при получении урона и автоматически заряжается.
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ ent-ActionTeleportSpell = Телепортация
|
||||
.desc = Позволяет телепортироваться в любое место на станции! Переносит вас в выбранное место.
|
||||
|
||||
ent-ActionKnock = Стук
|
||||
.desc = Открывает все двери и шлюзы в радиусе 4 тайлов.
|
||||
.desc = Открывает все двери, шлюзы и шкафы в радиусе 5 тайлов.
|
||||
|
||||
ent-ActionSmite = Кара
|
||||
.desc = Заряжает вашу руку мерзкой энергией, которую можно использовать для взрыва жертв. Заклинание требует, чтобы вы коснулись своей цели, поэтому вы не сможете использовать его в наручниках или будучи оглушённым. Не работает без волшебной мантии и шляпы.
|
||||
@@ -48,3 +48,6 @@ ent-ActionMindswapSpell = Подмена сознания
|
||||
|
||||
ent-ActionTimestopSpell = Остановка времени
|
||||
.desc = Останавливает время в радиусе вокруг вас. Находящиеся под воздействием существа не смогут двигаться, а пролетающие мимо снаряды будут остановлены до окончания остановки времени. Не работает без волшебной мантии и шляпы.
|
||||
|
||||
ent-ActionArcaneBarrageSpell = Магический залп
|
||||
.desc = Выстрелите потоком магической энергии в ваших врагов с помощью этого мощного заклинания. Для использования требуются обе свободные руки. Не работает без волшебной мантии и шляпы.
|
||||
|
||||
@@ -36,6 +36,11 @@ ent-ClothingOuterRealWizardFancy = мантия волшебника
|
||||
ent-ClothingHeadHelmetWizardHelmArmored = шлем мага
|
||||
.desc = Странный головной убор, который наверняка принадлежит настоящему магу. Не обладает свойствами волшебной шляпы.
|
||||
|
||||
ent-ArcaneBarrage = магический залп
|
||||
.desc = Пиу Пиу Пиу.
|
||||
|
||||
arcane-barrage-no-empty-hand = Вам нужна свободная рука для использования заклинания!
|
||||
|
||||
mindswap-success = Ваш разум подменили!
|
||||
mindswap-borer-failed = Его разумом кто-то управляет.
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
Blunt: 0.5
|
||||
Slash: 0.5
|
||||
Piercing: 0.5
|
||||
Shock: 1.2
|
||||
Shock: 0 # for lightning explosions
|
||||
Structural: 0.5
|
||||
flatReductions:
|
||||
Blunt: 10
|
||||
@@ -26,7 +26,7 @@
|
||||
- type: damageModifierSet
|
||||
id: StructuralMetallic
|
||||
coefficients:
|
||||
Shock: 1.2
|
||||
Shock: 0 # for lightning explosions
|
||||
Heat: 1.2
|
||||
flatReductions:
|
||||
Blunt: 10
|
||||
@@ -42,6 +42,7 @@
|
||||
Slash: 0.25
|
||||
Piercing: 0.75
|
||||
Heat: 0.9
|
||||
Shock: 0 # for lightning explosions
|
||||
flatReductions:
|
||||
Blunt: 5
|
||||
|
||||
@@ -50,7 +51,7 @@
|
||||
coefficients:
|
||||
Blunt: 2
|
||||
Piercing: 0.2
|
||||
Shock: 0.6
|
||||
Shock: 0 # for lightning explosions
|
||||
flatReductions:
|
||||
Piercing: 10
|
||||
|
||||
|
||||
@@ -546,6 +546,8 @@
|
||||
Piercing: 0.9
|
||||
Heat: 0.9
|
||||
- type: WizardClothes
|
||||
- type: FlashImmunity
|
||||
- type: EyeProtection
|
||||
|
||||
#Organic Space Suit
|
||||
- type: entity
|
||||
|
||||
@@ -697,7 +697,7 @@
|
||||
- PowerCell
|
||||
- PowerCellSmall
|
||||
- type: EnergyDomeGenerator
|
||||
damageEnergyDraw: 20
|
||||
damageEnergyDraw: 15
|
||||
domePrototype: EnergyDomeSmallPink
|
||||
- type: ClothingSpeedModifier
|
||||
walkModifier: 0.9
|
||||
|
||||
@@ -220,21 +220,21 @@
|
||||
- type: Projectile
|
||||
damage:
|
||||
types:
|
||||
Caustic: 10
|
||||
Shock: 10
|
||||
- type: Sprite
|
||||
sprite: Structures/Power/Generation/Tesla/energy_miniball.rsi
|
||||
layers:
|
||||
- state: tesla_projectile
|
||||
shader: unshaded
|
||||
- type: Explosive
|
||||
explosionType: Default
|
||||
maxIntensity: 100
|
||||
intensitySlope: 0.1
|
||||
totalIntensity: 0.3
|
||||
explosionType: Shock
|
||||
maxIntensity: 40
|
||||
intensitySlope: 6
|
||||
totalIntensity: 200
|
||||
maxTileBreak: 0
|
||||
- type: StunOnCollide
|
||||
stunAmount: 2
|
||||
knockdownAmount: 2
|
||||
stunAmount: 6
|
||||
knockdownAmount: 6
|
||||
- type: TeslaProjectile
|
||||
|
||||
- type: entity
|
||||
@@ -276,4 +276,3 @@
|
||||
- 0, 0, 1, 0.4
|
||||
- 1, 0, 1, 0.25
|
||||
- 1, 0, 0, 0.1
|
||||
optionsConcealable: true
|
||||
|
||||
@@ -1441,4 +1441,45 @@
|
||||
- type: Projectile
|
||||
damage:
|
||||
types:
|
||||
Piercing: 20
|
||||
Piercing: 25
|
||||
|
||||
- type: entity
|
||||
name: arcane bolt
|
||||
id: ArcaneBolt
|
||||
parent: BaseBullet
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: White/Objects/Weapons/arcane_barrage.rsi
|
||||
state: bullet
|
||||
- type: Ammo
|
||||
muzzleFlash: null
|
||||
- type: Projectile
|
||||
damage:
|
||||
types:
|
||||
Heat: 25
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
projectile:
|
||||
shape:
|
||||
!type:PhysShapeAabb
|
||||
bounds: "-0.2,-0.2,0.2,0.2"
|
||||
hard: false
|
||||
mask:
|
||||
- Opaque
|
||||
fly-by: *flybyfixture
|
||||
- type: Trail
|
||||
splineIteratorType: Linear
|
||||
splineRendererType: Continuous
|
||||
creationMethod: OnMove
|
||||
scale: 0.05, 0.0
|
||||
lifetime: 0.5
|
||||
randomWalk: 0.001, 0.001
|
||||
gravity: 0, 0
|
||||
gradient:
|
||||
- 1, 0, 0.75, 1
|
||||
- 1, 0, 0.75, 0
|
||||
- type: PointLight
|
||||
radius: 1.7
|
||||
color: purple
|
||||
energy: 0.7
|
||||
|
||||
@@ -15,4 +15,5 @@
|
||||
sprite: Objects/Magic/magicactions.rsi
|
||||
state: knock
|
||||
event: !type:KnockSpellEvent
|
||||
range: 5
|
||||
speech: action-speech-spell-knock
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
prototype: ProjectileTeslaBall
|
||||
posData: !type:TargetCasterPos
|
||||
- type: VariableUseDelay
|
||||
useDelay: 6
|
||||
altUseDelay: 12
|
||||
useDelay: 5
|
||||
altUseDelay: 5
|
||||
chargeUseDelay: 30
|
||||
|
||||
- type: entity
|
||||
@@ -361,3 +361,19 @@
|
||||
event: !type:StopTimeSpellEvent
|
||||
prototype: Timestop
|
||||
speech: "TOKI YO TOMARE!"
|
||||
|
||||
- type: entity
|
||||
id: ActionArcaneBarrageSpell
|
||||
name: Arcane barrage
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: Magic
|
||||
requiresClothes: true
|
||||
- type: InstantAction
|
||||
useDelay: 75
|
||||
itemIconStyle: BigAction
|
||||
icon:
|
||||
sprite: Objects/Magic/magicactions.rsi
|
||||
state: arcane_barrage
|
||||
event: !type:ArcaneBarrageSpellEvent
|
||||
prototype: ArcaneBarrage
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
capacity: 25
|
||||
- type: BoltBarrage
|
||||
- type: GiftIgnore
|
||||
- type: CultItem
|
||||
canPickUp: false
|
||||
|
||||
- type: cultistFactoryProduction
|
||||
id: FactoryCultBloodBarrage
|
||||
|
||||
@@ -29,3 +29,6 @@
|
||||
- type: TimedDespawn
|
||||
lifetime: 10
|
||||
- type: FreezeContacts
|
||||
- type: GravPulseOnStartup # Because physics sucks
|
||||
maxRange: 2.5
|
||||
baseRadialAcceleration: 0.1
|
||||
|
||||
@@ -169,3 +169,12 @@
|
||||
- type: Scroll
|
||||
actionId: ActionTimestopSpell
|
||||
learnPopup: scroll-component-timestop
|
||||
|
||||
- type: entity
|
||||
id: ScrollArcaneBarrage
|
||||
parent: BaseScroll
|
||||
name: "Arcane barrage scroll"
|
||||
components:
|
||||
- type: Scroll
|
||||
actionId: ActionArcaneBarrageSpell
|
||||
learnPopup: scroll-component-barrage
|
||||
|
||||
@@ -104,3 +104,31 @@
|
||||
Structural: 80
|
||||
- type: ChangeThrowForce
|
||||
throwForce: 20
|
||||
|
||||
- type: entity
|
||||
name: arcane barrage
|
||||
parent: BaseItem
|
||||
id: ArcaneBarrage
|
||||
description: Pew Pew Pew.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: White/Objects/Weapons/arcane_barrage.rsi
|
||||
state: icon
|
||||
- type: Item
|
||||
size: Ginormous
|
||||
sprite: White/Objects/Weapons/arcane_barrage.rsi
|
||||
- type: AmmoCounter
|
||||
- type: Gun
|
||||
fireRate: 4
|
||||
selectedMode: SemiAuto
|
||||
availableModes:
|
||||
- SemiAuto
|
||||
soundEmpty: null
|
||||
soundGunshot:
|
||||
path: /Audio/Weapons/emitter.ogg
|
||||
clumsyProof: true
|
||||
- type: BasicEntityAmmoProvider
|
||||
proto: ArcaneBolt
|
||||
capacity: 30
|
||||
- type: BoltBarrage
|
||||
- type: GiftIgnore
|
||||
|
||||
@@ -110,6 +110,22 @@
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: SpellBookArcaneBarrage
|
||||
name: spellbook-barrage-name
|
||||
description: spellbook-barrage-desc
|
||||
icon:
|
||||
sprite: Objects/Magic/magicactions.rsi
|
||||
state: arcane_barrage
|
||||
productEntity: ScrollArcaneBarrage
|
||||
cost:
|
||||
SpellPoint: 2
|
||||
categories:
|
||||
- AttackSpells
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: SpellBookBlink
|
||||
name: spellbook-blink-name
|
||||
@@ -273,7 +289,7 @@
|
||||
description: spellbook-hfrequency-desc
|
||||
productEntity: HighFrequencyBlade
|
||||
cost:
|
||||
SpellPoint: 2
|
||||
SpellPoint: 1
|
||||
categories:
|
||||
- MagicItems
|
||||
conditions:
|
||||
@@ -286,7 +302,7 @@
|
||||
description: spellbook-spellblade-desc
|
||||
productEntity: SpellBlade
|
||||
cost:
|
||||
SpellPoint: 2
|
||||
SpellPoint: 1
|
||||
categories:
|
||||
- MagicItems
|
||||
conditions:
|
||||
|
||||
@@ -150,3 +150,16 @@
|
||||
fireColor: Green
|
||||
texturePath: /Textures/Effects/fire_greyscale.rsi
|
||||
fireStates: 3
|
||||
|
||||
- type: explosion
|
||||
id: Shock
|
||||
damagePerIntensity:
|
||||
types:
|
||||
Shock: 15
|
||||
tileBreakChance: [0]
|
||||
tileBreakIntensity: [0]
|
||||
lightColor: "#B3CEFF"
|
||||
fireColor: "#B3CEFF"
|
||||
texturePath: /Textures/Effects/fire_greyscale.rsi
|
||||
fireStates: 3
|
||||
ignoreResistances: false
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 667 B |
@@ -63,6 +63,9 @@
|
||||
},
|
||||
{
|
||||
"name": "time"
|
||||
},
|
||||
{
|
||||
"name": "arcane_barrage"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 370 B |
Binary file not shown.
|
After Width: | Height: | Size: 667 B |
Binary file not shown.
|
After Width: | Height: | Size: 830 B |
Binary file not shown.
|
After Width: | Height: | Size: 799 B |
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from tgstation",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "icon"
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
],
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
],
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
],
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "inhand-right",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
],
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
],
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
],
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "bullet"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user