Diona Nymphs & Splitting (#24630)
* Porting & implementation * Fix two stupid errors * Human not humans * fix audio path * Fix test fails & update cooldown * Work on reviews & test fail * Rework nymph organ system. * Make the nymph organs nospawn. * IsDeadIC
This commit is contained in:
@@ -4,6 +4,7 @@ using Content.Server.IgnitionSource;
|
|||||||
using Content.Server.Stunnable;
|
using Content.Server.Stunnable;
|
||||||
using Content.Server.Temperature.Components;
|
using Content.Server.Temperature.Components;
|
||||||
using Content.Server.Temperature.Systems;
|
using Content.Server.Temperature.Systems;
|
||||||
|
using Content.Server.Damage.Components;
|
||||||
using Content.Shared.ActionBlocker;
|
using Content.Shared.ActionBlocker;
|
||||||
using Content.Shared.Alert;
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
@@ -20,6 +21,7 @@ using Content.Shared.Throwing;
|
|||||||
using Content.Shared.Timing;
|
using Content.Shared.Timing;
|
||||||
using Content.Shared.Toggleable;
|
using Content.Shared.Toggleable;
|
||||||
using Content.Shared.Weapons.Melee.Events;
|
using Content.Shared.Weapons.Melee.Events;
|
||||||
|
using Content.Shared.FixedPoint;
|
||||||
using Robust.Server.Audio;
|
using Robust.Server.Audio;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Physics.Events;
|
using Robust.Shared.Physics.Events;
|
||||||
@@ -73,6 +75,8 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
SubscribeLocalEvent<IgniteOnMeleeHitComponent, MeleeHitEvent>(OnMeleeHit);
|
SubscribeLocalEvent<IgniteOnMeleeHitComponent, MeleeHitEvent>(OnMeleeHit);
|
||||||
|
|
||||||
SubscribeLocalEvent<ExtinguishOnInteractComponent, ActivateInWorldEvent>(OnExtinguishActivateInWorld);
|
SubscribeLocalEvent<ExtinguishOnInteractComponent, ActivateInWorldEvent>(OnExtinguishActivateInWorld);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<IgniteOnHeatDamageComponent, DamageChangedEvent>(OnDamageChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMeleeHit(EntityUid uid, IgniteOnMeleeHitComponent component, MeleeHitEvent args)
|
private void OnMeleeHit(EntityUid uid, IgniteOnMeleeHitComponent component, MeleeHitEvent args)
|
||||||
@@ -318,6 +322,31 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
UpdateAppearance(uid, flammable);
|
UpdateAppearance(uid, flammable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnDamageChanged(EntityUid uid, IgniteOnHeatDamageComponent component, DamageChangedEvent args)
|
||||||
|
{
|
||||||
|
// Make sure the entity is flammable
|
||||||
|
if (!TryComp<FlammableComponent>(uid, out var flammable))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Make sure the damage delta isn't null
|
||||||
|
if (args.DamageDelta == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if its' taken any heat damage, and give the value
|
||||||
|
if (args.DamageDelta.DamageDict.TryGetValue("Heat", out FixedPoint2 value))
|
||||||
|
{
|
||||||
|
// Make sure the value is greater than the threshold
|
||||||
|
if(value <= component.Threshold)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Ignite that sucker
|
||||||
|
flammable.FireStacks += component.FireStacks;
|
||||||
|
Ignite(uid, uid, flammable);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public void Resist(EntityUid uid,
|
public void Resist(EntityUid uid,
|
||||||
FlammableComponent? flammable = null)
|
FlammableComponent? flammable = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using Content.Shared.Damage;
|
||||||
|
using Content.Shared.FixedPoint;
|
||||||
|
|
||||||
|
namespace Content.Server.Damage.Components;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class IgniteOnHeatDamageComponent : Component
|
||||||
|
{
|
||||||
|
[DataField("fireStacks")]
|
||||||
|
public float FireStacks = 1f;
|
||||||
|
|
||||||
|
// The minimum amount of damage taken to apply fire stacks
|
||||||
|
[DataField("threshold")]
|
||||||
|
public FixedPoint2 Threshold = 15;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Shared.Hands.Components;
|
using Content.Shared.Hands.Components;
|
||||||
using Content.Shared.Interaction.Components;
|
using Content.Shared.Interaction.Components;
|
||||||
using Content.Shared.Silicons.Borgs.Components;
|
using Content.Shared.Silicons.Borgs.Components;
|
||||||
|
|||||||
8
Content.Shared/Mind/Components/IsDeadICComponent.cs
Normal file
8
Content.Shared/Mind/Components/IsDeadICComponent.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Content.Shared.Mind.Components;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class IsDeadICComponent : Component
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
21
Content.Shared/Mind/IsDeadICSystem.cs
Normal file
21
Content.Shared/Mind/IsDeadICSystem.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using Content.Shared.Mind.Components;
|
||||||
|
|
||||||
|
namespace Content.Shared.Mind;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This marks any entity with the component as dead
|
||||||
|
/// for stuff like objectives & round-end
|
||||||
|
/// used for nymphs & reformed diona.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class IsDeadICSystem : EntitySystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<IsDeadICComponent, GetCharactedDeadIcEvent>(OnGetDeadIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGetDeadIC(EntityUid uid, IsDeadICComponent component, ref GetCharactedDeadIcEvent args)
|
||||||
|
{
|
||||||
|
args.Dead = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
30
Content.Shared/Species/Components/GibActionComponent.cs
Normal file
30
Content.Shared/Species/Components/GibActionComponent.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using Content.Shared.Mobs;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Species.Components;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||||
|
public sealed partial class GibActionComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The action to use.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("actionPrototype", required: true)]
|
||||||
|
public EntProtoId ActionPrototype;
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public EntityUid? ActionEntity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// What mob states the action will appear in
|
||||||
|
/// </summary>
|
||||||
|
[DataField("allowedStates"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public List<MobState> AllowedStates = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The text that appears when attempting to split.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("popupText")]
|
||||||
|
public string PopupText = "diona-gib-action-use";
|
||||||
|
}
|
||||||
24
Content.Shared/Species/Components/NymphComponent.cs
Normal file
24
Content.Shared/Species/Components/NymphComponent.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Species.Components;
|
||||||
|
/// <summary>
|
||||||
|
/// This will replace one entity with another entity when it is removed from a body part.
|
||||||
|
/// Obviously hyper-specific. If you somehow find another use for this, good on you.
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
public sealed partial class NymphComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The entity to replace the organ with.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(required: true)]
|
||||||
|
public EntProtoId EntityPrototype = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to transfer the mind to this new entity.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public bool TransferMind = false;
|
||||||
|
}
|
||||||
48
Content.Shared/Species/Components/ReformComponent.cs
Normal file
48
Content.Shared/Species/Components/ReformComponent.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Species.Components;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||||
|
public sealed partial class ReformComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The action to use.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(required: true)]
|
||||||
|
public EntProtoId ActionPrototype = default!;
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public EntityUid? ActionEntity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How long it will take to reform
|
||||||
|
/// </summary>
|
||||||
|
[DataField(required: true)]
|
||||||
|
public float ReformTime = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not the entity should start with a cooldown
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public bool StartDelayed = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not the entity should be stunned when reforming at all
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public bool ShouldStun = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The text that appears when attempting to reform
|
||||||
|
/// </summary>
|
||||||
|
[DataField(required: true)]
|
||||||
|
public string PopupText;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The mob that our entity will reform into
|
||||||
|
/// </summary>
|
||||||
|
[DataField(required: true)]
|
||||||
|
public EntProtoId ReformPrototype { get; private set; }
|
||||||
|
}
|
||||||
61
Content.Shared/Species/Systems/GibActionSystem.cs
Normal file
61
Content.Shared/Species/Systems/GibActionSystem.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
using Content.Shared.Species.Components;
|
||||||
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.Body.Systems;
|
||||||
|
using Content.Shared.Mobs;
|
||||||
|
using Content.Shared.Mobs.Components;
|
||||||
|
using Content.Shared.Popups;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Content.Shared.Species;
|
||||||
|
|
||||||
|
public sealed partial class GibActionSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
||||||
|
[Dependency] private readonly SharedBodySystem _bodySystem = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<GibActionComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||||
|
SubscribeLocalEvent<GibActionComponent, GibActionEvent>(OnGibAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMobStateChanged(EntityUid uid, GibActionComponent comp, MobStateChangedEvent args)
|
||||||
|
{
|
||||||
|
// When the mob changes state, check if they're dead and give them the action if so.
|
||||||
|
if (!TryComp<MobStateComponent>(uid, out var mobState))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_protoManager.TryIndex<EntityPrototype>(comp.ActionPrototype, out var actionProto))
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var allowedState in comp.AllowedStates)
|
||||||
|
{
|
||||||
|
if(allowedState == mobState.CurrentState)
|
||||||
|
{
|
||||||
|
// The mob should never have more than 1 state so I don't see this being an issue
|
||||||
|
_actionsSystem.AddAction(uid, ref comp.ActionEntity, comp.ActionPrototype);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If they aren't given the action, remove it.
|
||||||
|
_actionsSystem.RemoveAction(uid, comp.ActionEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGibAction(EntityUid uid, GibActionComponent comp, GibActionEvent args)
|
||||||
|
{
|
||||||
|
// When they use the action, gib them.
|
||||||
|
_popupSystem.PopupClient(Loc.GetString(comp.PopupText, ("name", uid)), uid, uid);
|
||||||
|
_bodySystem.GibBody(uid, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public sealed partial class GibActionEvent : InstantActionEvent { }
|
||||||
|
}
|
||||||
41
Content.Shared/Species/Systems/NymphSystem.cs
Normal file
41
Content.Shared/Species/Systems/NymphSystem.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using Content.Shared.Species.Components;
|
||||||
|
using Content.Shared.Body.Events;
|
||||||
|
using Content.Shared.Mind;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
|
namespace Content.Shared.Species;
|
||||||
|
|
||||||
|
public sealed partial class NymphSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] protected readonly IPrototypeManager _protoManager = default!;
|
||||||
|
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
|
||||||
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<NymphComponent, RemovedFromPartInBodyEvent>(OnRemovedFromPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRemovedFromPart(EntityUid uid, NymphComponent comp, RemovedFromPartInBodyEvent args)
|
||||||
|
{
|
||||||
|
if (!_timing.IsFirstTimePredicted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (TerminatingOrDeleted(uid) || TerminatingOrDeleted(args.OldBody))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_protoManager.TryIndex<EntityPrototype>(comp.EntityPrototype, out var entityProto))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var coords = Transform(uid).Coordinates;
|
||||||
|
var nymph = EntityManager.SpawnEntity(entityProto.ID, coords);
|
||||||
|
|
||||||
|
if (comp.TransferMind == true && _mindSystem.TryGetMind(args.OldBody, out var mindId, out var mind))
|
||||||
|
_mindSystem.TransferTo(mindId, nymph, mind: mind);
|
||||||
|
|
||||||
|
EntityManager.QueueDeleteEntity(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
108
Content.Shared/Species/Systems/ReformSystem.cs
Normal file
108
Content.Shared/Species/Systems/ReformSystem.cs
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
using Content.Shared.Species.Components;
|
||||||
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Stunnable;
|
||||||
|
using Content.Shared.Mind;
|
||||||
|
using Content.Shared.Humanoid;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
using Robust.Shared.Serialization.Manager;
|
||||||
|
|
||||||
|
namespace Content.Shared.Species;
|
||||||
|
|
||||||
|
public sealed partial class ReformSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
||||||
|
[Dependency] private readonly INetManager _netMan = default!;
|
||||||
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||||||
|
[Dependency] private readonly SharedStunSystem _stunSystem = default!;
|
||||||
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
|
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
|
||||||
|
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||||
|
[Dependency] private readonly ISerializationManager _serializationManager = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ReformComponent, MapInitEvent>(OnMapInit);
|
||||||
|
SubscribeLocalEvent<ReformComponent, ComponentShutdown>(OnCompRemove);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ReformComponent, ReformEvent>(OnReform);
|
||||||
|
SubscribeLocalEvent<ReformComponent, ReformDoAfterEvent>(OnDoAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMapInit(EntityUid uid, ReformComponent comp, MapInitEvent args)
|
||||||
|
{
|
||||||
|
// When the map is initialized, give them the action
|
||||||
|
if (comp.ActionPrototype != default && !_protoManager.TryIndex<EntityPrototype>(comp.ActionPrototype, out var actionProto))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_actionsSystem.AddAction(uid, ref comp.ActionEntity, out var reformAction, comp.ActionPrototype);
|
||||||
|
|
||||||
|
// See if the action should start with a delay, and give it that starting delay if so.
|
||||||
|
if (comp.StartDelayed && reformAction != null && reformAction.UseDelay != null)
|
||||||
|
{
|
||||||
|
var start = _gameTiming.CurTime;
|
||||||
|
var end = _gameTiming.CurTime + reformAction.UseDelay.Value;
|
||||||
|
|
||||||
|
_actionsSystem.SetCooldown(comp.ActionEntity!.Value, start, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCompRemove(EntityUid uid, ReformComponent comp, ComponentShutdown args)
|
||||||
|
{
|
||||||
|
_actionsSystem.RemoveAction(uid, comp.ActionEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnReform(EntityUid uid, ReformComponent comp, ReformEvent args)
|
||||||
|
{
|
||||||
|
// Stun them when they use the action for the amount of reform time.
|
||||||
|
if (comp.ShouldStun)
|
||||||
|
_stunSystem.TryStun(uid, TimeSpan.FromSeconds(comp.ReformTime), true);
|
||||||
|
_popupSystem.PopupClient(Loc.GetString(comp.PopupText, ("name", uid)), uid, uid);
|
||||||
|
|
||||||
|
// Create a doafter & start it
|
||||||
|
var doAfter = new DoAfterArgs(EntityManager, uid, comp.ReformTime, new ReformDoAfterEvent(), uid)
|
||||||
|
{
|
||||||
|
BreakOnUserMove = true,
|
||||||
|
BlockDuplicate = true,
|
||||||
|
BreakOnDamage = true,
|
||||||
|
CancelDuplicate = true,
|
||||||
|
RequireCanInteract = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
_doAfterSystem.TryStartDoAfter(doAfter);
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDoAfter(EntityUid uid, ReformComponent comp, ReformDoAfterEvent args)
|
||||||
|
{
|
||||||
|
if (args.Cancelled || args.Handled || comp.Deleted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_netMan.IsClient)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Spawn a new entity
|
||||||
|
// This is, to an extent, taken from polymorph. I don't use polymorph for various reasons- most notably that this is permanent.
|
||||||
|
var child = Spawn(comp.ReformPrototype, Transform(uid).Coordinates);
|
||||||
|
|
||||||
|
// This transfers the mind to the new entity
|
||||||
|
if (_mindSystem.TryGetMind(uid, out var mindId, out var mind))
|
||||||
|
_mindSystem.TransferTo(mindId, child, mind: mind);
|
||||||
|
|
||||||
|
// Delete the old entity
|
||||||
|
QueueDel(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed partial class ReformEvent : InstantActionEvent { }
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed partial class ReformDoAfterEvent : SimpleDoAfterEvent { }
|
||||||
|
}
|
||||||
@@ -131,4 +131,10 @@
|
|||||||
- files: ["dog_bark3.ogg"]
|
- files: ["dog_bark3.ogg"]
|
||||||
license: "CC0-1.0"
|
license: "CC0-1.0"
|
||||||
copyright: "Audio is recorded/created by KFerentchak 'FreeSound.org'. The original audio was trimmed and renamed"
|
copyright: "Audio is recorded/created by KFerentchak 'FreeSound.org'. The original audio was trimmed and renamed"
|
||||||
source: "https://freesound.org/people/KFerentchak/sounds/235912/"
|
source: "https://freesound.org/people/KFerentchak/sounds/235912/"
|
||||||
|
|
||||||
|
- files: ["nymph_chirp.ogg"]
|
||||||
|
license: "CC-BY-SA-3.0"
|
||||||
|
copyright: "Taken from ParadiseSS13"
|
||||||
|
source: "https://github.com/ParadiseSS13/Paradise/commit/a34f1054cef5a44a67fdac3b67b811137c6071dd"
|
||||||
|
|
||||||
BIN
Resources/Audio/Animals/nymph_chirp.ogg
Normal file
BIN
Resources/Audio/Animals/nymph_chirp.ogg
Normal file
Binary file not shown.
3
Resources/Locale/en-US/actions/actions/diona.ftl
Normal file
3
Resources/Locale/en-US/actions/actions/diona.ftl
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
diona-gib-action-use = {$name} splits apart in an instant!
|
||||||
|
|
||||||
|
diona-reform-attempt = {$name} attempts to reform!
|
||||||
@@ -31,6 +31,7 @@ petting-success-bear = You reluctantly pet {THE($target)} on {POSS-ADJ($target)}
|
|||||||
petting-success-slimes = You pet {THE($target)} on {POSS-ADJ($target)} mucous surface.
|
petting-success-slimes = You pet {THE($target)} on {POSS-ADJ($target)} mucous surface.
|
||||||
petting-success-snake = You pet {THE($target)} on {POSS-ADJ($target)} scaly large head.
|
petting-success-snake = You pet {THE($target)} on {POSS-ADJ($target)} scaly large head.
|
||||||
petting-success-monkey = You pet {THE($target)} on {POSS-ADJ($target)} mischevious little head.
|
petting-success-monkey = You pet {THE($target)} on {POSS-ADJ($target)} mischevious little head.
|
||||||
|
petting-success-nymph = You pet {THE($target)} on {POSS-ADJ($target)} wooden little head.
|
||||||
|
|
||||||
petting-failure-generic = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} aloof towards you.
|
petting-failure-generic = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} aloof towards you.
|
||||||
|
|
||||||
@@ -51,6 +52,7 @@ petting-failure-dragon = You raise your hand, but as {THE($target)} roars, you d
|
|||||||
petting-failure-hamster = You reach out to pet {THE($target)}, but {SUBJECT($target)} attempts to bite your finger and only your quick reflexes save you from an almost fatal injury.
|
petting-failure-hamster = You reach out to pet {THE($target)}, but {SUBJECT($target)} attempts to bite your finger and only your quick reflexes save you from an almost fatal injury.
|
||||||
petting-failure-bear = You reach out to pet {THE($target)}, but {SUBJECT($target)} growls, making you think twice.
|
petting-failure-bear = You reach out to pet {THE($target)}, but {SUBJECT($target)} growls, making you think twice.
|
||||||
petting-failure-monkey = You reach out to pet {THE($target)}, but {SUBJECT($target)} almost bites your fingers!
|
petting-failure-monkey = You reach out to pet {THE($target)}, but {SUBJECT($target)} almost bites your fingers!
|
||||||
|
petting-failure-nymph = You reach out to pet {THE($target)}, but {POSS-ADJ($target)} moves their branches away.
|
||||||
petting-failure-shadow = You're trying to pet {THE($target)}, but your hand passes through the cold darkness of his body.
|
petting-failure-shadow = You're trying to pet {THE($target)}, but your hand passes through the cold darkness of his body.
|
||||||
|
|
||||||
## Petting silicons
|
## Petting silicons
|
||||||
|
|||||||
21
Resources/Prototypes/Actions/diona.yml
Normal file
21
Resources/Prototypes/Actions/diona.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
- type: entity
|
||||||
|
id: DionaGibAction
|
||||||
|
name: Gib Yourself!
|
||||||
|
description: Split apart into 3 nymphs.
|
||||||
|
noSpawn: true
|
||||||
|
components:
|
||||||
|
- type: InstantAction
|
||||||
|
icon: Mobs/Species/Diona/organs.rsi/brain.png
|
||||||
|
event: !type:GibActionEvent {}
|
||||||
|
checkCanInteract: false
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: DionaReformAction
|
||||||
|
name: Reform
|
||||||
|
description: Reform back into a whole Diona.
|
||||||
|
noSpawn: true
|
||||||
|
components:
|
||||||
|
- type: InstantAction
|
||||||
|
icon: Mobs/Species/Diona/parts.rsi/full.png
|
||||||
|
event: !type:ReformEvent {}
|
||||||
|
useDelay: 300 # Once every 10 minutes. Keep them dead for a fair bit before reforming
|
||||||
@@ -48,18 +48,6 @@
|
|||||||
reagents:
|
reagents:
|
||||||
- ReagentId: UncookedAnimalProteins
|
- ReagentId: UncookedAnimalProteins
|
||||||
Quantity: 5
|
Quantity: 5
|
||||||
- type: Brain
|
|
||||||
- type: InputMover
|
|
||||||
- type: Examiner
|
|
||||||
- type: Lung #lungs in they head. why they there tho?
|
|
||||||
- type: Metabolizer
|
|
||||||
removeEmpty: true
|
|
||||||
solutionOnBody: false
|
|
||||||
solution: "Lung"
|
|
||||||
metabolizerTypes: [ Plant ]
|
|
||||||
groups:
|
|
||||||
- id: Gas
|
|
||||||
rateModifier: 100.0
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: OrganDionaEyes
|
id: OrganDionaEyes
|
||||||
@@ -102,3 +90,104 @@
|
|||||||
- id: Narcotic
|
- id: Narcotic
|
||||||
- id: Alcohol
|
- id: Alcohol
|
||||||
rateModifier: 0.1
|
rateModifier: 0.1
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: OrganDionaLungs
|
||||||
|
parent: BaseDionaOrgan
|
||||||
|
name: lungs
|
||||||
|
description: "Filters oxygen from an atmosphere, which is then sent into the bloodstream to be used as an electron carrier."
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Mobs/Species/Human/organs.rsi
|
||||||
|
layers:
|
||||||
|
- state: lung-l
|
||||||
|
- state: lung-r
|
||||||
|
- type: Lung
|
||||||
|
- type: Metabolizer
|
||||||
|
removeEmpty: true
|
||||||
|
solutionOnBody: false
|
||||||
|
solution: "Lung"
|
||||||
|
metabolizerTypes: [ Plant ]
|
||||||
|
groups:
|
||||||
|
- id: Gas
|
||||||
|
rateModifier: 100.0
|
||||||
|
- type: SolutionContainerManager
|
||||||
|
solutions:
|
||||||
|
organ:
|
||||||
|
maxVol: 10
|
||||||
|
reagents:
|
||||||
|
- ReagentId: Nutriment
|
||||||
|
Quantity: 10
|
||||||
|
Lung:
|
||||||
|
maxVol: 100
|
||||||
|
canReact: False
|
||||||
|
|
||||||
|
# Organs that turn into nymphs on removal
|
||||||
|
- type: entity
|
||||||
|
id: OrganDionaBrainNymph
|
||||||
|
parent: OrganDionaBrain
|
||||||
|
noSpawn: true
|
||||||
|
name: brain
|
||||||
|
description: "The source of incredible, unending intelligence. Honk."
|
||||||
|
components:
|
||||||
|
- type: Brain
|
||||||
|
- type: Nymph # This will make the organs turn into a nymph when they're removed.
|
||||||
|
entityPrototype: OrganDionaNymphBrain
|
||||||
|
transferMind: true
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: OrganDionaStomachNymph
|
||||||
|
parent: OrganDionaStomach
|
||||||
|
noSpawn: true
|
||||||
|
name: stomach
|
||||||
|
description: "Gross. This is hard to stomach."
|
||||||
|
components:
|
||||||
|
- type: Nymph
|
||||||
|
entityPrototype: OrganDionaNymphStomach
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: OrganDionaLungsNymph
|
||||||
|
parent: OrganDionaLungs
|
||||||
|
noSpawn: true
|
||||||
|
name: lungs
|
||||||
|
description: "Filters oxygen from an atmosphere, which is then sent into the bloodstream to be used as an electron carrier."
|
||||||
|
components:
|
||||||
|
- type: Nymph
|
||||||
|
entityPrototype: OrganDionaNymphLungs
|
||||||
|
|
||||||
|
# Nymphs that the organs will turn into
|
||||||
|
- type: entity
|
||||||
|
id: OrganDionaNymphBrain
|
||||||
|
parent: MobDionaNymph
|
||||||
|
noSpawn: true
|
||||||
|
name: diona nymph
|
||||||
|
suffix: Brain
|
||||||
|
description: Contains the brain of a formerly fully-formed Diona. Killing this would kill the Diona forever. You monster.
|
||||||
|
components:
|
||||||
|
- type: IsDeadIC
|
||||||
|
- type: Body
|
||||||
|
prototype: AnimalNymphBrain
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: OrganDionaNymphStomach
|
||||||
|
parent: MobDionaNymph
|
||||||
|
noSpawn: true
|
||||||
|
name: diona nymph
|
||||||
|
suffix: Stomach
|
||||||
|
description: Contains the stomach of a formerly fully-formed Diona. It doesn't taste any better for it.
|
||||||
|
components:
|
||||||
|
- type: IsDeadIC
|
||||||
|
- type: Body
|
||||||
|
prototype: AnimalNymphStomach
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: OrganDionaNymphLungs
|
||||||
|
parent: MobDionaNymph
|
||||||
|
noSpawn: true
|
||||||
|
name: diona nymph
|
||||||
|
suffix: Lungs
|
||||||
|
description: Contains the lungs of a formerly fully-formed Diona. Breathtaking.
|
||||||
|
components:
|
||||||
|
- type: IsDeadIC
|
||||||
|
- type: Body
|
||||||
|
prototype: AnimalNymphLungs
|
||||||
|
|||||||
66
Resources/Prototypes/Body/Prototypes/Animal/nymph.yml
Normal file
66
Resources/Prototypes/Body/Prototypes/Animal/nymph.yml
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
- type: body
|
||||||
|
id: AnimalNymphBrain
|
||||||
|
name: "nymph"
|
||||||
|
root: torso
|
||||||
|
slots:
|
||||||
|
torso:
|
||||||
|
part: TorsoAnimal
|
||||||
|
connections:
|
||||||
|
- legs
|
||||||
|
organs:
|
||||||
|
brain: OrganDionaBrain
|
||||||
|
lungs: OrganAnimalLungs
|
||||||
|
stomach: OrganAnimalStomach
|
||||||
|
liver: OrganAnimalLiver
|
||||||
|
heart: OrganAnimalHeart
|
||||||
|
kidneys: OrganAnimalKidneys
|
||||||
|
legs:
|
||||||
|
part: LegsAnimal
|
||||||
|
connections:
|
||||||
|
- feet
|
||||||
|
feet:
|
||||||
|
part: FeetAnimal
|
||||||
|
|
||||||
|
- type: body
|
||||||
|
id: AnimalNymphLungs
|
||||||
|
name: "nymph"
|
||||||
|
root: torso
|
||||||
|
slots:
|
||||||
|
torso:
|
||||||
|
part: TorsoAnimal
|
||||||
|
connections:
|
||||||
|
- legs
|
||||||
|
organs:
|
||||||
|
lungs: OrganDionaLungs
|
||||||
|
stomach: OrganAnimalStomach
|
||||||
|
liver: OrganAnimalLiver
|
||||||
|
heart: OrganAnimalHeart
|
||||||
|
kidneys: OrganAnimalKidneys
|
||||||
|
legs:
|
||||||
|
part: LegsAnimal
|
||||||
|
connections:
|
||||||
|
- feet
|
||||||
|
feet:
|
||||||
|
part: FeetAnimal
|
||||||
|
|
||||||
|
- type: body
|
||||||
|
id: AnimalNymphStomach
|
||||||
|
name: "nymph"
|
||||||
|
root: torso
|
||||||
|
slots:
|
||||||
|
torso:
|
||||||
|
part: TorsoAnimal
|
||||||
|
connections:
|
||||||
|
- legs
|
||||||
|
organs:
|
||||||
|
lungs: OrganAnimalLungs
|
||||||
|
stomach: OrganDionaStomach
|
||||||
|
liver: OrganAnimalLiver
|
||||||
|
heart: OrganAnimalHeart
|
||||||
|
kidneys: OrganAnimalKidneys
|
||||||
|
legs:
|
||||||
|
part: LegsAnimal
|
||||||
|
connections:
|
||||||
|
- feet
|
||||||
|
feet:
|
||||||
|
part: FeetAnimal
|
||||||
@@ -8,8 +8,7 @@
|
|||||||
connections:
|
connections:
|
||||||
- torso
|
- torso
|
||||||
organs:
|
organs:
|
||||||
brain: OrganDionaBrain
|
brain: OrganDionaBrainNymph
|
||||||
eyes: OrganDionaEyes
|
|
||||||
torso:
|
torso:
|
||||||
part: TorsoDiona
|
part: TorsoDiona
|
||||||
connections:
|
connections:
|
||||||
@@ -18,7 +17,8 @@
|
|||||||
- right leg
|
- right leg
|
||||||
- left leg
|
- left leg
|
||||||
organs:
|
organs:
|
||||||
stomach: OrganDionaStomach
|
stomach: OrganDionaStomachNymph
|
||||||
|
lungs: OrganDionaLungsNymph
|
||||||
right arm:
|
right arm:
|
||||||
part: RightArmDiona
|
part: RightArmDiona
|
||||||
connections:
|
connections:
|
||||||
|
|||||||
@@ -3099,3 +3099,77 @@
|
|||||||
factions:
|
factions:
|
||||||
- Passive
|
- Passive
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: diona nymph
|
||||||
|
parent: SimpleMobBase
|
||||||
|
id: MobDionaNymph
|
||||||
|
description: It's like a cat, only.... branch-ier.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
drawdepth: Mobs
|
||||||
|
layers:
|
||||||
|
- map: ["enum.DamageStateVisualLayers.Base"]
|
||||||
|
state: nymph
|
||||||
|
sprite: Mobs/Animals/nymph.rsi
|
||||||
|
- type: Physics
|
||||||
|
- type: Fixtures
|
||||||
|
fixtures:
|
||||||
|
fix1:
|
||||||
|
shape:
|
||||||
|
!type:PhysShapeCircle
|
||||||
|
radius: 0.35
|
||||||
|
density: 100 # High, because wood is heavy.
|
||||||
|
mask:
|
||||||
|
- MobMask
|
||||||
|
layer:
|
||||||
|
- MobLayer
|
||||||
|
- type: Inventory
|
||||||
|
speciesId: cat
|
||||||
|
templateId: pet
|
||||||
|
- type: InventorySlots
|
||||||
|
- type: Strippable
|
||||||
|
- type: Bloodstream
|
||||||
|
bloodReagent: Water
|
||||||
|
bloodMaxVolume: 60
|
||||||
|
- type: UserInterface
|
||||||
|
interfaces:
|
||||||
|
- key: enum.StrippingUiKey.Key
|
||||||
|
type: StrippableBoundUserInterface
|
||||||
|
- type: DamageStateVisuals
|
||||||
|
states:
|
||||||
|
Alive:
|
||||||
|
Base: nymph
|
||||||
|
Critical:
|
||||||
|
Base: nymph_sleep
|
||||||
|
Dead:
|
||||||
|
Base: nymph_dead
|
||||||
|
- type: Butcherable
|
||||||
|
spawned:
|
||||||
|
- id: MaterialWoodPlank1
|
||||||
|
amount: 2
|
||||||
|
- type: InteractionPopup
|
||||||
|
successChance: 0.7
|
||||||
|
interactSuccessString: petting-success-nymph
|
||||||
|
interactFailureString: petting-failure-nymph
|
||||||
|
interactSuccessSound:
|
||||||
|
path: /Audio/Animals/nymph_chirp.ogg
|
||||||
|
- type: MobThresholds
|
||||||
|
thresholds:
|
||||||
|
0: Alive
|
||||||
|
30: Critical
|
||||||
|
60: Dead
|
||||||
|
- type: MovementSpeedModifier
|
||||||
|
baseWalkSpeed : 2.5
|
||||||
|
baseSprintSpeed : 4.5
|
||||||
|
- type: Grammar
|
||||||
|
attributes:
|
||||||
|
gender: epicene
|
||||||
|
- type: Speech
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- VimPilot
|
||||||
|
- type: Reform
|
||||||
|
actionPrototype: DionaReformAction
|
||||||
|
reformTime: 10
|
||||||
|
popupText: diona-reform-attempt
|
||||||
|
reformPrototype: MobDionaReformed
|
||||||
|
|||||||
@@ -11,3 +11,13 @@
|
|||||||
damageRecovery:
|
damageRecovery:
|
||||||
types:
|
types:
|
||||||
Asphyxiation: -1.0
|
Asphyxiation: -1.0
|
||||||
|
|
||||||
|
# Reformed Diona
|
||||||
|
- type: entity
|
||||||
|
parent: MobDiona
|
||||||
|
noSpawn: true
|
||||||
|
id: MobDionaReformed
|
||||||
|
name: Reformed Diona
|
||||||
|
components:
|
||||||
|
- type: IsDeadIC
|
||||||
|
- type: RandomHumanoidAppearance
|
||||||
@@ -94,6 +94,13 @@
|
|||||||
- type: BodyEmotes
|
- type: BodyEmotes
|
||||||
soundsId: DionaBodyEmotes
|
soundsId: DionaBodyEmotes
|
||||||
- type: IgnoreKudzu
|
- type: IgnoreKudzu
|
||||||
|
- type: IgniteOnHeatDamage
|
||||||
|
fireStacks: 1
|
||||||
|
threshold: 12
|
||||||
|
- type: GibAction
|
||||||
|
actionPrototype: DionaGibAction
|
||||||
|
allowedStates:
|
||||||
|
- Dead
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseSpeciesDummy
|
parent: BaseSpeciesDummy
|
||||||
|
|||||||
BIN
Resources/Textures/Mobs/Animals/nymph.rsi/icon.png
Normal file
BIN
Resources/Textures/Mobs/Animals/nymph.rsi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 611 B |
63
Resources/Textures/Mobs/Animals/nymph.rsi/meta.json
Normal file
63
Resources/Textures/Mobs/Animals/nymph.rsi/meta.json
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "https://github.com/ParadiseSS13/Paradise/commit/f367d7de199969a5fb5054de44faa5618092f487",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "nymph",
|
||||||
|
"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,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
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": "nymph_dead"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "nymph_sleep",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
Resources/Textures/Mobs/Animals/nymph.rsi/nymph.png
Normal file
BIN
Resources/Textures/Mobs/Animals/nymph.rsi/nymph.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
BIN
Resources/Textures/Mobs/Animals/nymph.rsi/nymph_dead.png
Normal file
BIN
Resources/Textures/Mobs/Animals/nymph.rsi/nymph_dead.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 655 B |
BIN
Resources/Textures/Mobs/Animals/nymph.rsi/nymph_sleep.png
Normal file
BIN
Resources/Textures/Mobs/Animals/nymph.rsi/nymph_sleep.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Reference in New Issue
Block a user