Crystals Update (#925)

* portal frame

* resprited sharpening stone

* portal frame entity

* darkness -> dimension magic type

* thaumaturgy platforms, some refactor

* magic energy refactor

* Update AirlockPryingTest.cs

* transfering tweaks

* fixed magic manipulation
This commit is contained in:
Ed
2025-02-25 23:37:05 +03:00
committed by GitHub
parent 4e62a0efcc
commit ba901d5e0e
48 changed files with 340 additions and 409 deletions

View File

@@ -6,6 +6,7 @@ namespace Content.IntegrationTests.Tests.Doors;
public sealed class AirlockPryingTest : InteractionTest
{
/* CP14 Crowbar door prying disabled
[Test]
public async Task PoweredClosedAirlock_Pry_DoesNotOpen()
{
@@ -81,4 +82,5 @@ public sealed class AirlockPryingTest : InteractionTest
Assert.That(doorComp.State, Is.EqualTo(DoorState.Closing), "Unpowered airlock failed to pry closed.");
}
*/
}

View File

@@ -34,7 +34,7 @@ public sealed partial class CP14ManaChange : EntityEffect
}
var magicSystem = args.EntityManager.System<CP14MagicEnergySystem>();
magicSystem.ChangeEnergy(args.TargetEntity, ManaDelta * scale, Safe);
magicSystem.ChangeEnergy(args.TargetEntity, ManaDelta * scale, out _, out _, safe: Safe);
if (args.EntityManager.TryGetComponent<CP14MagicEnergyCrystalSlotComponent>(args.TargetEntity,
out var crystalSlot))

View File

@@ -42,6 +42,9 @@ public sealed partial class CP14DemiplaneSystem
if (map is null)
continue;
if (!stabilizer.Enabled)
continue;
if (stabilizer.RequireAlive && !(_mobState.IsAlive(uid) || _mobState.IsCritical(uid)))
continue;

View File

@@ -137,7 +137,7 @@ public sealed partial class CP14MagicEnergyCrystalSlotSystem : SharedCP14MagicEn
return false;
}
_magicEnergy.ChangeEnergy(energyEnt.Value, energyComp, energy, safe);
_magicEnergy.ChangeEnergy(energyEnt.Value, energy, out _, out _, energyComp, safe);
return true;
}
}

View File

@@ -28,7 +28,7 @@ public partial class CP14MagicEnergySystem
if (!ent.Comp.Damage.TryGetValue(dict.Key, out var modifier))
continue;
ChangeEnergy(ent, modifier * dict.Value, true);
ChangeEnergy(ent, modifier * dict.Value, out _, out _, safe: true);
}
}
@@ -56,7 +56,7 @@ public partial class CP14MagicEnergySystem
draw.NextUpdateTime = _gameTiming.CurTime + TimeSpan.FromSeconds(draw.Delay);
ChangeEnergy(uid, magicContainer, draw.Energy, draw.Safe);
ChangeEnergy(uid, draw.Energy, out _, out _, magicContainer, draw.Safe);
}
var query2 = EntityQueryEnumerator<CP14MagicEnergyPhotosynthesisComponent, CP14MagicEnergyContainerComponent>();
@@ -67,7 +67,7 @@ public partial class CP14MagicEnergySystem
draw.NextUpdateTime = _gameTiming.CurTime + TimeSpan.FromSeconds(draw.Delay);
ChangeEnergy(uid, magicContainer, _dayCycle.TryDaylightThere(uid) ? draw.DaylightEnergy : draw.DarknessEnergy, true);
ChangeEnergy(uid, _dayCycle.TryDaylightThere(uid) ? draw.DaylightEnergy : draw.DarknessEnergy, out _, out _, magicContainer, true);
}
}
@@ -87,7 +87,7 @@ public partial class CP14MagicEnergySystem
if (!_magicSlot.TryGetEnergyCrystalFromSlot(uid, out var energyEnt, out var energyComp))
continue;
ChangeEnergy(energyEnt.Value, energyComp, draw.Energy, draw.Safe);
ChangeEnergy(energyEnt.Value, draw.Energy, out _, out _, energyComp, draw.Safe);
}
}
}

View File

@@ -0,0 +1,61 @@
using System.Linq;
using Content.Server._CP14.MagicEnergy.Components;
using Content.Server.DeviceLinking.Systems;
using Content.Shared._CP14.MagicEnergy.Components;
using Content.Shared.DeviceLinking;
namespace Content.Server._CP14.MagicEnergy;
public partial class CP14MagicEnergySystem
{
[Dependency] private readonly DeviceLinkSystem _signal = default!;
[ValidatePrototypeId<SinkPortPrototype>]
public const string PowerSinkPort = "CP14PowerTarget";
[ValidatePrototypeId<SourcePortPrototype>]
public const string PowerSourcePort = "CP14PowerSource";
private void InitializePortRelay()
{
SubscribeLocalEvent<CP14MagicEnergyPortRelayComponent, MapInitEvent>(OnPortRelayInit);
}
private void UpdatePortRelay(float frameTime)
{
var query = EntityQueryEnumerator<CP14MagicEnergyPortRelayComponent, CP14MagicEnergyContainerComponent, DeviceLinkSourceComponent>();
while (query.MoveNext(out var uid, out var relay, out var container, out var link))
{
if (relay.NextUpdateTime > _gameTiming.CurTime)
continue;
//Мы ищем все порты, которые связаны с этим источником, и если они равны "CP14Target", то мы передаем им энергию
foreach (var (sinkUid, linkedPair) in link.LinkedPorts)
{
var passed = false;
foreach (var (source, sink) in linkedPair)
{
if (source == PowerSourcePort && sink == PowerSinkPort)
{
passed = true;
}
}
if (passed)
{
TransferEnergy(uid, sinkUid, relay.Energy, out _, out _, container, safe: relay.Safe);
}
}
relay.NextUpdateTime = _gameTiming.CurTime + TimeSpan.FromSeconds(relay.Delay);
}
}
private void OnPortRelayInit(Entity<CP14MagicEnergyPortRelayComponent> ent, ref MapInitEvent args)
{
if (ent.Comp.SinkPort is not null)
_signal.EnsureSinkPorts(ent, ent.Comp.SinkPort.Value);
if (ent.Comp.SourcePort is not null)
_signal.EnsureSourcePorts(ent, ent.Comp.SourcePort.Value);
}
}

View File

@@ -12,6 +12,7 @@ public sealed partial class CP14MagicEnergySystem : SharedCP14MagicEnergySystem
{
InitializeDraw();
InitializeScanner();
InitializePortRelay();
}
public override void Update(float frameTime)
@@ -19,5 +20,6 @@ public sealed partial class CP14MagicEnergySystem : SharedCP14MagicEnergySystem
base.Update(frameTime);
UpdateDraw(frameTime);
UpdatePortRelay(frameTime);
}
}

View File

@@ -0,0 +1,33 @@
using Content.Shared.DeviceLinking;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.MagicEnergy.Components;
/// <summary>
/// Allows you to relay magical energy to other objects through signal sustem
/// </summary>
[RegisterComponent, Access(typeof(CP14MagicEnergySystem))]
public sealed partial class CP14MagicEnergyPortRelayComponent : Component
{
[DataField]
public ProtoId<SinkPortPrototype>? SinkPort = CP14MagicEnergySystem.PowerSinkPort;
[DataField]
public ProtoId<SourcePortPrototype>? SourcePort = CP14MagicEnergySystem.PowerSourcePort;
[DataField]
public bool Enable = true;
[DataField]
public bool Safe = true;
[DataField]
public float Delay = 5f;
[DataField]
public FixedPoint2 Energy = 5f;
[DataField]
public TimeSpan NextUpdateTime { get; set; } = TimeSpan.Zero;
}

View File

@@ -7,6 +7,7 @@ using Content.Shared._CP14.MagicSpell;
using Content.Shared._CP14.MagicSpell.Components;
using Content.Shared._CP14.MagicSpell.Events;
using Content.Shared._CP14.MagicSpell.Spells;
using Content.Shared.FixedPoint;
using Content.Shared.Projectiles;
using Content.Shared.Throwing;
using Content.Shared.Weapons.Melee.Events;
@@ -123,29 +124,24 @@ public sealed partial class CP14MagicSystem : CP14SharedMagicSystem
var requiredMana = CalculateManacost(ent, args.Performer);
if (magicEffect.SpellStorage is not null &&
TryComp<CP14MagicEnergyContainerComponent>(magicEffect.SpellStorage, out var magicStorage))
//First - used object
if (magicEffect.SpellStorage is not null && TryComp<CP14MagicEnergyContainerComponent>(magicEffect.SpellStorage, out var magicStorage))
{
var spellEv = new CP14SpellFromSpellStorageUsedEvent(args.Performer, (ent, magicEffect), requiredMana);
RaiseLocalEvent(magicEffect.SpellStorage.Value, ref spellEv);
if (magicStorage.Energy > 0)
{
var cashedEnergy = magicStorage.Energy;
if (_magicEnergy.TryConsumeEnergy(magicEffect.SpellStorage.Value, requiredMana, magicStorage, false))
requiredMana = MathF.Max(0, (float)(requiredMana - cashedEnergy));
}
_magicEnergy.ChangeEnergy(magicEffect.SpellStorage.Value, -requiredMana, out var changedEnergy, out var overloadedEnergy, magicStorage, safe: false);
requiredMana -= FixedPoint2.Abs(changedEnergy + overloadedEnergy);
}
//Second - action user
if (requiredMana > 0 &&
TryComp<CP14MagicEnergyContainerComponent>(args.Performer, out var playerMana))
{
_magicEnergy.TryConsumeEnergy(args.Performer.Value, requiredMana, safe: false);
_magicEnergy.ChangeEnergy(args.Performer.Value, -requiredMana, out _, out _, playerMana, safe: false);
}
}
private void OnMusicCheck(Entity<CP14MagicEffectRequiredMusicToolComponent> ent, ref CP14CastMagicEffectAttemptEvent args)
{
var passed = false;

View File

@@ -11,4 +11,7 @@ public sealed partial class CP14DemiplaneStabilizerComponent : Component
/// </summary>
[DataField]
public bool RequireAlive = false;
[DataField]
public bool Enabled = true;
}

View File

@@ -20,4 +20,10 @@ public sealed partial class CP14MagicEnergyContainerComponent : Component
[DataField]
public ProtoId<AlertPrototype>? MagicAlert = null;
/// <summary>
/// Does this container support unsafe energy manipulation?
/// </summary>
[DataField]
public bool UnsafeSupport = false;
}

View File

@@ -45,91 +45,102 @@ public partial class SharedCP14MagicEnergySystem : EntitySystem
("color", color));
}
public void ChangeEnergy(EntityUid uid, FixedPoint2 energy, bool safe = false)
public void ChangeEnergy(EntityUid uid,
FixedPoint2 energy,
out FixedPoint2 changedEnergy,
out FixedPoint2 overloadEnergy,
CP14MagicEnergyContainerComponent? component = null,
bool safe = false)
{
if (!TryComp<CP14MagicEnergyContainerComponent>(uid, out var energyContainer))
changedEnergy = 0;
overloadEnergy = 0;
if (!Resolve(uid, ref component))
return;
ChangeEnergy(uid, energyContainer, energy, safe);
}
public void ChangeEnergy(EntityUid uid, CP14MagicEnergyContainerComponent component, FixedPoint2 energy, bool safe = false)
{
if (!safe)
{
//Overload
if (component.Energy + energy > component.MaxEnergy)
if (component.Energy + energy > component.MaxEnergy && component.UnsafeSupport)
{
RaiseLocalEvent(uid, new CP14MagicEnergyOverloadEvent()
{
OverloadEnergy = (component.Energy + energy) - component.MaxEnergy,
});
overloadEnergy = (component.Energy + energy) - component.MaxEnergy;
RaiseLocalEvent(uid,
new CP14MagicEnergyOverloadEvent()
{
OverloadEnergy = (component.Energy + energy) - component.MaxEnergy,
});
}
//Burn out
if (component.Energy + energy < 0)
if (component.Energy + energy < 0 && component.UnsafeSupport)
{
RaiseLocalEvent(uid, new CP14MagicEnergyBurnOutEvent()
{
BurnOutEnergy = -energy - component.Energy
});
overloadEnergy = component.Energy + energy;
RaiseLocalEvent(uid,
new CP14MagicEnergyBurnOutEvent()
{
BurnOutEnergy = -energy - component.Energy
});
}
}
var oldEnergy = component.Energy;
var newEnergy = Math.Clamp((float)component.Energy + (float)energy, 0, (float)component.MaxEnergy);
changedEnergy = newEnergy - oldEnergy;
component.Energy = newEnergy;
if (oldEnergy != newEnergy)
{
RaiseLocalEvent(uid, new CP14MagicEnergyLevelChangeEvent()
{
OldValue = oldEnergy,
NewValue = newEnergy,
MaxValue = component.MaxEnergy,
});
RaiseLocalEvent(uid,
new CP14MagicEnergyLevelChangeEvent()
{
OldValue = oldEnergy,
NewValue = newEnergy,
MaxValue = component.MaxEnergy,
});
}
UpdateMagicAlert((uid, component));
}
public void TransferEnergy(EntityUid from,
EntityUid to,
FixedPoint2 energy,
out FixedPoint2 changedEnergy,
out FixedPoint2 overloadEnergy,
CP14MagicEnergyContainerComponent? fromComponent = null,
CP14MagicEnergyContainerComponent? toComponent = null,
bool safe = false)
{
changedEnergy = 0;
overloadEnergy = 0;
if (!Resolve(from, ref fromComponent) || !Resolve(to, ref toComponent))
return;
var transferEnergy = energy;
//We check how much space is left in the container so as not to overload it, but only if it does not support overloading
if (!toComponent.UnsafeSupport || safe)
{
var freeSpace = toComponent.MaxEnergy - toComponent.Energy;
transferEnergy = FixedPoint2.Min(freeSpace, energy);
}
ChangeEnergy(from, -transferEnergy, out var change, out var overload, fromComponent, safe);
ChangeEnergy(to , -(change + overload), out changedEnergy, out overloadEnergy, toComponent, safe);
}
public bool HasEnergy(EntityUid uid, FixedPoint2 energy, CP14MagicEnergyContainerComponent? component = null, bool safe = false)
{
if (!Resolve(uid, ref component))
return false;
if (safe == false)
if (safe == false && component.UnsafeSupport)
return true;
return component.Energy >= energy;
}
public bool TryConsumeEnergy(EntityUid uid, FixedPoint2 energy, CP14MagicEnergyContainerComponent? component = null, bool safe = false)
{
if (!Resolve(uid, ref component))
return false;
if (energy <= 0)
return true;
// Attempting to absorb more energy than is contained in the container available only in non-safe methods (with container destruction)
if (component.Energy < energy)
{
if (safe)
{
return false;
}
else
{
ChangeEnergy(uid, component, -energy, safe);
return true;
}
}
ChangeEnergy(uid, component, -energy, safe);
return true;
}
private void UpdateMagicAlert(Entity<CP14MagicEnergyContainerComponent> ent)
{
if (ent.Comp.MagicAlert == null)

View File

@@ -12,9 +12,6 @@ public sealed partial class CP14SpellConsumeManaEffect : CP14SpellEffect
[DataField]
public bool Safe = false;
[DataField]
public float LossMultiplier = 1.0f;
public override void Effect(EntityManager entManager, CP14SpellEffectBaseArgs args)
{
if (args.Target is null)
@@ -22,40 +19,30 @@ public sealed partial class CP14SpellConsumeManaEffect : CP14SpellEffect
var targetEntity = args.Target.Value;
if (!entManager.TryGetComponent<CP14MagicEnergyContainerComponent>(targetEntity, out var magicContainer))
return;
var magicEnergy = entManager.System<SharedCP14MagicEnergySystem>();
var currentMana = magicContainer.Energy;
FixedPoint2 manaBuffer = MathF.Min(Mana.Float(), currentMana.Float()) * LossMultiplier;
if (!magicEnergy.TryConsumeEnergy(targetEntity, Mana, magicContainer, Safe))
return;
//OK, we consume mana (or health?) from target, and now we put it in used object or caster
//First - used object
if (manaBuffer > 0 && entManager.TryGetComponent<CP14MagicEnergyContainerComponent>(args.Used, out var usedMagicStorage))
if (args.Used is not null)
{
var freeSpace = usedMagicStorage.MaxEnergy - usedMagicStorage.Energy;
if (freeSpace < manaBuffer)
{
magicEnergy.ChangeEnergy(args.Used.Value, usedMagicStorage, freeSpace, true);
manaBuffer -= freeSpace;
}
else
{
magicEnergy.ChangeEnergy(args.Used.Value, usedMagicStorage, manaBuffer, true);
manaBuffer = 0;
}
magicEnergy.TransferEnergy(targetEntity,
args.Used.Value,
Mana,
out _,
out _,
safe: Safe);
return;
}
//Second - action user
if (manaBuffer > 0 && entManager.TryGetComponent<CP14MagicEnergyContainerComponent>(args.User, out var userMagicStorage))
//Second - player
if (args.User is not null)
{
magicEnergy.ChangeEnergy(args.User.Value, userMagicStorage, manaBuffer, Safe);
magicEnergy.TransferEnergy(targetEntity,
args.User.Value,
Mana,
out _,
out _,
safe: Safe);
return;
}
}
}

View File

@@ -3,7 +3,7 @@ cp14-magic-type-water = Water
cp14-magic-type-earth = Earth
cp14-magic-type-healing = Healing
cp14-magic-type-light = Light
cp14-magic-type-darkness = Darkness
cp14-magic-type-dimension = Dimension
cp14-magic-type-meta = Metamagic
cp14-magic-type-necro = Necromancy

View File

@@ -2,4 +2,10 @@ cp14-signal-port-name-pressed = Нажато
cp14-signal-port-description-pressed = Этот узел активируется, когда на устройство нажимают.
cp14-signal-port-name-released = Отпущено
cp14-signal-port-description-released = Этот узел активируется, когда устройство отпускают.
cp14-signal-port-description-released = Этот узел активируется, когда устройство отпускают.
cp14-signal-port-name-power-source = Источник энергии
cp14-signal-port-description-power-source = Этот узел активируется когда устройство отправляет заряд энергии. Будучи связанным с портом "Приемник энергии", будет передавать туда энергию.
cp14-signal-port-name-power-target = Приемник энергии
cp14-signal-port-description-hold-power-target = Этот узел активируется, когда устройство принимает заряд энергии. Будучи связанным с портом "Источник энергии", будет получать от него энергию.

View File

@@ -3,7 +3,7 @@ cp14-magic-type-water = Вода
cp14-magic-type-earth = Земля
cp14-magic-type-healing = Исцеление
cp14-magic-type-light = Свет
cp14-magic-type-darkness = Тьма
cp14-magic-type-dimension = Пространство
cp14-magic-type-meta = Метамагия
cp14-magic-type-necro = Некромантия

View File

@@ -0,0 +1,4 @@
- type: sinkPort
id: CP14PowerTarget
name: cp14-signal-port-name-power-target
description: cp14-signal-port-description-hold-power-target

View File

@@ -8,4 +8,10 @@
id: CP14Released
name: cp14-signal-port-name-released
description: cp14-signal-port-description-released
defaultLinks: [ Toggle, Trigger, Timer ]
defaultLinks: [ Toggle, Trigger, Timer ]
- type: sourcePort
id: CP14PowerSource
name: cp14-signal-port-name-power-source
description: cp14-signal-port-description-power-source
defaultLinks: [ CP14PowerTarget ]

View File

@@ -9,7 +9,7 @@
- type: CP14MagicEffectManaCost
manaCost: 25
- type: CP14MagicEffect
magicType: Darkness
magicType: Dimension
telegraphyEffects:
- !type:CP14SpellSpawnEntityOnTarget
spawns:
@@ -54,7 +54,7 @@
shader: unshaded
- type: entity
parent: CP14BaseSpellScrollDarkness
parent: CP14BaseSpellScrollDimension
id: CP14SpellScrollDemiplaneInfiltration
name: demiplane infiltration spell scroll
components:

View File

@@ -9,7 +9,7 @@
- type: CP14MagicEffectManaCost
manaCost: 25
- type: CP14MagicEffect
magicType: Darkness
magicType: Dimension
telegraphyEffects:
- !type:CP14SpellSpawnEntityOnTarget
spawns:
@@ -67,7 +67,7 @@
- type: CP14MonolithTimedPassway
- type: entity
parent: CP14BaseSpellScrollDarkness
parent: CP14BaseSpellScrollDimension
id: CP14SpellScrollMonolithWarp
name: demiplane link spell scroll
components:

View File

@@ -9,7 +9,7 @@
- type: CP14MagicEffectManaCost
manaCost: 10
- type: CP14MagicEffect
magicType: Darkness
magicType: Dimension
telegraphyEffects:
- !type:CP14SpellSpawnEntityOnTarget
spawns:
@@ -52,7 +52,7 @@
color: "#5e427e"
- type: entity
parent: CP14BaseSpellScrollDarkness
parent: CP14BaseSpellScrollDimension
id: CP14SpellScrollShadowGrab
name: shadow grab spell scroll
components:

View File

@@ -11,7 +11,7 @@
- type: CP14MagicEffectManaCost
manaCost: 20
- type: CP14MagicEffect
magicType: Darkness
magicType: Dimension
telegraphyEffects:
- !type:CP14SpellSpawnEntityOnTarget
spawns:
@@ -45,7 +45,7 @@
color: "#5e427e"
- type: entity
parent: CP14BaseSpellScrollDarkness
parent: CP14BaseSpellScrollDimension
id: CP14SpellScrollShadowStep
name: shadow step spell scroll
components:

View File

@@ -51,7 +51,6 @@
- !type:CP14SpellConsumeManaEffect
safe: true
mana: 20
lossMultiplier: 1
- type: entity
id: CP14RuneManaConsume

View File

@@ -125,7 +125,7 @@
- type: entity
abstract: true
id: CP14BaseSpellScrollDarkness
id: CP14BaseSpellScrollDimension
parent: CP14BaseSpellScroll
components:
- type: Sprite

View File

@@ -2,8 +2,9 @@
save: false
parent:
- BaseMob
- CP14MobDamageable
- MobCombat
- CP14MobDamageable
- CP14MobMagical
id: CP14BaseMobSpecies
categories: [ ForkFiltered ]
abstract: true
@@ -210,18 +211,6 @@
- type: Tag
tags:
- FootstepSound
- type: CP14MagicCasterSlowdown
- type: CP14MagicEnergyContainer
magicAlert: CP14MagicEnergy
maxEnergy: 100
energy: 100
- type: CP14MagicEnergyDraw
energy: 1
delay: 3 # 5m to full restore
- type: CP14MagicUnsafeDamage
- type: CP14MagicUnsafeSleep
- type: CP14MagicAttuningMind
autoCopyToMind: true
- type: CP14DemiplaneStabilizer
requireAlive: true
- type: CanEnterCryostorage

View File

@@ -107,6 +107,8 @@
templateId: CP14Human
- type: TransferMindOnGib
- type: CP14KnowledgeStorage
- type: CP14DemiplaneStabilizer
enabled: false
- type: entity
parent: CP14BaseSpeciesDummy

View File

@@ -29,6 +29,26 @@
sound:
collection: MeatLaserImpact
- type: entity
id: CP14MobMagical
abstract: true
categories: [ ForkFiltered ]
components:
- type: CP14MagicCasterSlowdown
- type: CP14MagicEnergyContainer
magicAlert: CP14MagicEnergy
maxEnergy: 100
energy: 100
unsafeSupport: true
- type: CP14MagicEnergyDraw
energy: 1
delay: 3 # 5m to full restore
- type: CP14MagicUnsafeDamage
- type: CP14MagicUnsafeSleep
- type: CP14MagicAttuningMind
autoCopyToMind: true
- type: entity
parent:
- CP14MobDamageable

View File

@@ -34,6 +34,7 @@
magicAlert: CP14MagicEnergy
maxEnergy: 50
energy: 0
unsafeSupport: false
- type: CP14MagicEnergyExaminable
- type: CP14SpellStorageAccessHolding
- type: CP14SpellStorage

View File

@@ -82,7 +82,7 @@
components:
- type: CP14MagicManacostModify
modifiers:
Darkness: 1.4
Dimension: 1.4
- type: CP14SpellStorage
spells:
- CP14ActionSpellShadowStep

View File

@@ -1,187 +0,0 @@
- type: entity
id: CP14DangerousMobSpawnCrystal
name: unstable demiplane link crystal
description: Capable of opening many portals summoning creepy creatures if not destroyed in time! Hurry up! When it runs out of mana, it will start to collapse!
parent: BaseStructure
categories: [ ForkFiltered ]
components:
- type: SpriteFade
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-0.15,-0.2,0.15,0.2"
density: 1000
layer:
- WallLayer
- type: Sprite
noRot: true
sprite: _CP14/Structures/Specific/Thaumaturgy/demiplane_link_crystal.rsi
layers:
- state: warning
color: red
drawdepth: Mobs
offset: 0,0.9
- type: PointLight
enabled: true
color: red
energy: 3
radius: 10
- type: LightBehaviour
behaviours:
- !type:PulseBehaviour
interpolate: Cubic
maxDuration: 1
minValue: 1.0
maxValue: 40.0
property: Energy
isLooped: true
enabled: true
- type: MeleeSound
soundGroups:
Brute:
collection: GlassSmash
- type: Damageable
- type: Destructible
thresholds:
# First wave
- trigger:
!type:DamageTrigger
damage: 50
behaviors:
- !type:SpawnEntitiesBehavior
offset: 6
spawn:
CP14MobGroupSpawnerMosquito:
min: 1
max: 1
# Second wave
- trigger:
!type:DamageTrigger
damage: 100
behaviors:
- !type:SpawnEntitiesBehavior
offset: 6
spawn:
CP14MobGroupSpawnerHydras:
min: 1
max: 1
# Third wave
- trigger:
!type:DamageTrigger
damage: 200
behaviors:
- !type:SpawnEntitiesBehavior
offset: 6
spawn:
CP14MobGroupSpawnerIceSpectres:
min: 1
max: 1
- !type:SpawnEntitiesBehavior
offset: 6
spawn:
CP14MobGroupSpawnerZombie:
min: 1
max: 1
# Destroyed Yay!
- trigger:
!type:DamageTrigger
damage: 300
behaviors:
- !type:SpawnEntitiesBehavior # Reward
offset: 5
spawn:
CP14SpawnerDemiplaneLootT1:
min: 4
max: 8
- !type:SpawnEntitiesBehavior
offset: 2
spawn:
CP14DemiplaneKeyT2:
min: 1
max: 1
- !type:SpawnEntitiesBehavior # Exit
spawn:
CP14DemiplanePasswayRed:
min: 1
max: 1
- !type:PlaySoundBehavior #SFX
sound:
collection: GlassBreak
- !type:PlaySoundBehavior
sound:
path: /Audio/Effects/demon_dies.ogg
params:
pitch: 1.5
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: CP14MagicEnergyExaminable
- type: CP14MagicEnergyContainer
maxEnergy: 600
energy: 600
- type: CP14MagicEnergyDraw
energy: -6
delay: 6 # 10m to discharge
safe: false
- type: CP14MagicUnsafeTrigger
- type: DeleteOnTrigger
- type: SpawnOnTrigger
proto: CP14MobGroupSpawnerRandom
- type: CP14DemiplaneStabilizer
- type: AmbientSound
volume: 20
range: 15
sound:
path: /Audio/_CP14/Effects/demiplane_heartbeat.ogg
- type: entity
parent: MarkerBase
name: mob group random spawner
id: CP14MobGroupSpawnerRandom
suffix: Spawn self copy out of demiplane
categories: [ ForkFiltered ]
components:
- type: CP14SpawnOutOfDemiplane
- type: EntityTableSpawner
offset: 3
table: !type:GroupSelector
rolls: !type:RangeNumberSelector
range: 2, 2
children:
- id: CP14MobGroupSpawnerIceSpectres
- id: CP14MobGroupSpawnerZombie
- type: entity
id: CP14AutoDemiplaneKeyT1
parent: CP14DemiplaneKeyT1
suffix: T1 Unstable rift event, Auto Open
components:
- type: CP14DemiplaneAutoOpen
- type: CP14DemiplaneGeneratorData
autoRifts:
- CP14DemiplanRiftCore
- CP14DemiplanePasswayRed
selectedModifiers:
- EntryRoom
- UnstableDemiplaneCrystal #Spawn exit when broken
- TimeLimit10
- type: entity
id: CP14AutoDemiplaneKeyT2
parent: CP14DemiplaneKeyT2
suffix: T2 Unstable rift event, Auto Open
components:
- type: CP14DemiplaneAutoOpen
- type: CP14DemiplaneGeneratorData
autoRifts:
- CP14DemiplanRiftCore
- CP14DemiplanePasswayRed
selectedModifiers:
- EntryRoom
- UnstableDemiplaneCrystal #Spawn exit when broken
- TimeLimit10

View File

@@ -1,20 +1,12 @@
- type: entity
id: CP14DemiplaneLinkCrystal
parent: BaseStructure
categories: [ ForkFiltered ]
name: demiplane link crystal
description: Maintains communication with the demiplanes while charged. Causes mosnters from the demiplanes to attack the city. Once it is discharged, the game is over.
suffix: ONE TO MAP
placement:
mode: SnapgridCenter
snap:
- Wall
components:
- type: Transform
anchored: true
- type: SpriteFade
- type: Clickable
- type: Physics
bodyType: Static
- type: Fixtures
fixtures:
fix1:
@@ -26,12 +18,12 @@
- WallLayer
- type: Sprite
noRot: true
sprite: _CP14/Structures/Specific/Thaumaturgy/demiplane_link_crystal.rsi
sprite: _CP14/Structures/Specific/Thaumaturgy/energy_monolith_big.rsi
layers:
- state: full
- state: dimension
- state: frame
drawdepth: Mobs
offset: 0,0.9
offset: 0,0.8
- type: PointLight
enabled: true
color: "#8f42ff"
@@ -60,4 +52,45 @@
volume: 5
range: 10
sound:
path: /Audio/_CP14/Effects/demiplane_heartbeat.ogg
path: /Audio/_CP14/Effects/demiplane_heartbeat.ogg
- type: entity
id: CP14PortalFrameCrystal
categories: [ ForkFiltered ]
parent: BaseStructure
name: portal frame
description: A structure made of shadow crystals used to create a stable portal to another location.
components:
- type: Transform
anchored: true
- type: Clickable
- type: Physics
bodyType: Static
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-0.25,-0.25,0.25,0.25"
density: 60
mask:
- MachineMask
layer:
- MidImpassable
- LowImpassable
- type: Tag
tags:
- Structure
- type: Sprite
noRot: true
sprite: _CP14/Structures/Specific/Thaumaturgy/energy_monolith_small.rsi
layers:
- state: dimension
- state: frame
drawdepth: Mobs
offset: 0,0.4
- type: CP14MagicEnergyContainer
maxEnergy: 100
energy: 100
- type: CP14MagicEnergyExaminable
- type: CP14MagicEnergyPortRelay

View File

@@ -27,8 +27,6 @@
- id: CP14MosquitoSpawn
- id: CP14RabbitsSpawn
- id: CP14FrogsSpawn
#- id: CP14UnstableDemiplaneT1
#- id: CP14UnstableDemiplaneT2
- type: entity
parent: CP14BaseStationEventShortDelay
@@ -113,38 +111,4 @@
- type: VentCrittersRule
entries:
- id: CP14MobGroupSpawnerFrogs
prob: 0.08
#- type: entity
# parent: CP14BaseStationEventShortDelay
# id: CP14UnstableDemiplaneT1
# components:
# - type: StationEvent
# startAnnouncement: cp14-event-announcement-unstable-demiplane
# startAudio:
# path: /Audio/_CP14/Ambience/event_boom.ogg
# earliestStart: 20
# minimumPlayers: 15
# weight: 5
# duration: 60
# - type: VentCrittersRule
# specialEntries:
# - id: CP14AutoDemiplaneKeyT1
# prob: 0.001
#
#- type: entity
# parent: CP14BaseStationEventShortDelay
# id: CP14UnstableDemiplaneT2
# components:
# - type: StationEvent
# startAnnouncement: cp14-event-announcement-unstable-demiplane
# startAudio:
# path: /Audio/_CP14/Ambience/event_boom.ogg
# earliestStart: 20
# minimumPlayers: 30
# weight: 5
# duration: 60
# - type: VentCrittersRule
# specialEntries:
# - id: CP14AutoDemiplaneKeyT2
# prob: 0.001
prob: 0.08

View File

@@ -19,8 +19,8 @@
color: "#ba97b8"
- type: magicType
id: Darkness
name: cp14-magic-type-darkness
id: Dimension
name: cp14-magic-type-dimension
color: "#4e0691"
- type: magicType

View File

@@ -1,12 +1,3 @@
- type: cp14DemiplaneModifier
id: UnstableDemiplaneCrystal
layers:
- !type:OreDunGen
entity: CP14DangerousMobSpawnCrystal
count: 1
minGroupSize: 1
maxGroupSize: 1
- type: cp14DemiplaneModifier
id: EntryRoom
generationProb: 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1,7 +1,7 @@
{
"version": 1,
"license": "CC-BY-SA-4.0",
"copyright": "Created by TheShuEd (Github) , modified by vladimir.s",
"copyright": "Created by TheShuEd (Github) , modified by vladimir.s and Jaraten",
"size": {
"x": 32,
"y": 32

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 833 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,35 +0,0 @@
{
"version": 1,
"license": "All right reserved",
"copyright": "Created by vladimir.s ",
"size": {
"x": 48,
"y": 84
},
"states": [
{
"name": "full"
},
{
"name": "empty"
},
{
"name": "frame"
},
{
"name": "warning",
"delays": [
[
0.3,
0.1,
0.1,
0.1,
0.3,
0.1,
0.1,
0.1
]
]
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

View File

@@ -0,0 +1,17 @@
{
"version": 1,
"license": "All right reserved",
"copyright": "Created by vladimir.s ",
"size": {
"x": 48,
"y": 84
},
"states": [
{
"name": "dimension"
},
{
"name": "frame"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

View File

@@ -0,0 +1,17 @@
{
"version": 1,
"license": "All right reserved",
"copyright": "Created by TheShuEd for CrystallEdge",
"size": {
"x": 32,
"y": 48
},
"states": [
{
"name": "frame"
},
{
"name": "dimension"
}
]
}