prop hunt ss14 (real) (#26691)
* texture appropriation * add code for projector * add chameleon projector yml * damage and actions * prevent small props being killed round removing you (700 damage from a single shot) * tweak default * oop * do appearance properly, need engine update * fix bugs, blacklist pda * remove status icons * amou * sus * fix test + make props fast * amouuuung * remove funny log --------- Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using Content.Shared.Body.Components;
|
||||||
using Content.Shared.CardboardBox;
|
using Content.Shared.CardboardBox;
|
||||||
using Content.Shared.CardboardBox.Components;
|
using Content.Shared.CardboardBox.Components;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
@@ -13,9 +14,14 @@ public sealed class CardboardBoxSystem : SharedCardboardBoxSystem
|
|||||||
[Dependency] private readonly TransformSystem _transform = default!;
|
[Dependency] private readonly TransformSystem _transform = default!;
|
||||||
[Dependency] private readonly ExamineSystemShared _examine = default!;
|
[Dependency] private readonly ExamineSystemShared _examine = default!;
|
||||||
|
|
||||||
|
private EntityQuery<BodyComponent> _bodyQuery;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
|
_bodyQuery = GetEntityQuery<BodyComponent>();
|
||||||
|
|
||||||
SubscribeNetworkEvent<PlayBoxEffectMessage>(OnBoxEffect);
|
SubscribeNetworkEvent<PlayBoxEffectMessage>(OnBoxEffect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,6 +65,10 @@ public sealed class CardboardBoxSystem : SharedCardboardBoxSystem
|
|||||||
if (!_examine.InRangeUnOccluded(sourcePos, mapPos, box.Distance, null))
|
if (!_examine.InRangeUnOccluded(sourcePos, mapPos, box.Distance, null))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// no effect for anything too exotic
|
||||||
|
if (!_bodyQuery.HasComp(mob))
|
||||||
|
continue;
|
||||||
|
|
||||||
var ent = Spawn(box.Effect, mapPos);
|
var ent = Spawn(box.Effect, mapPos);
|
||||||
|
|
||||||
if (!xformQuery.TryGetComponent(ent, out var entTransform) || !TryComp<SpriteComponent>(ent, out var sprite))
|
if (!xformQuery.TryGetComponent(ent, out var entTransform) || !TryComp<SpriteComponent>(ent, out var sprite))
|
||||||
|
|||||||
33
Content.Client/Polymorph/Systems/ChameleonProjectorSystem.cs
Normal file
33
Content.Client/Polymorph/Systems/ChameleonProjectorSystem.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using Content.Shared.Chemistry.Components;
|
||||||
|
using Content.Shared.Polymorph.Components;
|
||||||
|
using Content.Shared.Polymorph.Systems;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Client.Polymorph.Systems;
|
||||||
|
|
||||||
|
public sealed class ChameleonProjectorSystem : SharedChameleonProjectorSystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
|
|
||||||
|
private EntityQuery<AppearanceComponent> _appearanceQuery;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
_appearanceQuery = GetEntityQuery<AppearanceComponent>();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ChameleonDisguiseComponent, AfterAutoHandleStateEvent>(OnHandleState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnHandleState(Entity<ChameleonDisguiseComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||||
|
{
|
||||||
|
CopyComp<SpriteComponent>(ent);
|
||||||
|
CopyComp<GenericVisualizerComponent>(ent);
|
||||||
|
CopyComp<SolutionContainerVisualsComponent>(ent);
|
||||||
|
|
||||||
|
// reload appearance to hopefully prevent any invisible layers
|
||||||
|
if (_appearanceQuery.TryComp(ent, out var appearance))
|
||||||
|
_appearance.QueueUpdate(ent, appearance);
|
||||||
|
}
|
||||||
|
}
|
||||||
99
Content.Server/Polymorph/Systems/ChameleonProjectorSystem.cs
Normal file
99
Content.Server/Polymorph/Systems/ChameleonProjectorSystem.cs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
using Content.Server.Polymorph.Components;
|
||||||
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.Construction.Components;
|
||||||
|
using Content.Shared.Hands;
|
||||||
|
using Content.Shared.Mobs;
|
||||||
|
using Content.Shared.Mobs.Components;
|
||||||
|
using Content.Shared.Mobs.Systems;
|
||||||
|
using Content.Shared.Polymorph;
|
||||||
|
using Content.Shared.Polymorph.Components;
|
||||||
|
using Content.Shared.Polymorph.Systems;
|
||||||
|
using Content.Shared.StatusIcon.Components;
|
||||||
|
using Robust.Shared.Physics.Components;
|
||||||
|
|
||||||
|
namespace Content.Server.Polymorph.Systems;
|
||||||
|
|
||||||
|
public sealed class ChameleonProjectorSystem : SharedChameleonProjectorSystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly MetaDataSystem _meta = default!;
|
||||||
|
[Dependency] private readonly MobThresholdSystem _mobThreshold = default!;
|
||||||
|
[Dependency] private readonly PolymorphSystem _polymorph = default!;
|
||||||
|
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
||||||
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
|
[Dependency] private readonly SharedTransformSystem _xform = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ChameleonDisguiseComponent, GotEquippedHandEvent>(OnEquippedHand);
|
||||||
|
SubscribeLocalEvent<ChameleonDisguiseComponent, DisguiseToggleNoRotEvent>(OnToggleNoRot);
|
||||||
|
SubscribeLocalEvent<ChameleonDisguiseComponent, DisguiseToggleAnchoredEvent>(OnToggleAnchored);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEquippedHand(Entity<ChameleonDisguiseComponent> ent, ref GotEquippedHandEvent args)
|
||||||
|
{
|
||||||
|
if (!TryComp<PolymorphedEntityComponent>(ent, out var poly))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_polymorph.Revert((ent, poly));
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Disguise(ChameleonProjectorComponent proj, EntityUid user, EntityUid entity)
|
||||||
|
{
|
||||||
|
if (_polymorph.PolymorphEntity(user, proj.Polymorph) is not {} disguise)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// make disguise look real (for simple things at least)
|
||||||
|
var meta = MetaData(entity);
|
||||||
|
_meta.SetEntityName(disguise, meta.EntityName);
|
||||||
|
_meta.SetEntityDescription(disguise, meta.EntityDescription);
|
||||||
|
|
||||||
|
var comp = EnsureComp<ChameleonDisguiseComponent>(disguise);
|
||||||
|
comp.SourceEntity = entity;
|
||||||
|
comp.SourceProto = Prototype(entity)?.ID;
|
||||||
|
Dirty(disguise, comp);
|
||||||
|
|
||||||
|
// no sechud trolling
|
||||||
|
RemComp<StatusIconComponent>(disguise);
|
||||||
|
|
||||||
|
_appearance.CopyData(entity, disguise);
|
||||||
|
|
||||||
|
var mass = CompOrNull<PhysicsComponent>(entity)?.Mass ?? 0f;
|
||||||
|
|
||||||
|
// let the disguise die when its taken enough damage, which then transfers to the player
|
||||||
|
// health is proportional to mass, and capped to not be insane
|
||||||
|
if (TryComp<MobThresholdsComponent>(disguise, out var thresholds))
|
||||||
|
{
|
||||||
|
// if the player is of flesh and blood, cap max health to theirs
|
||||||
|
// so that when reverting damage scales 1:1 and not round removing
|
||||||
|
var playerMax = _mobThreshold.GetThresholdForState(user, MobState.Dead).Float();
|
||||||
|
var max = playerMax == 0f ? proj.MaxHealth : Math.Max(proj.MaxHealth, playerMax);
|
||||||
|
|
||||||
|
var health = Math.Clamp(mass, proj.MinHealth, proj.MaxHealth);
|
||||||
|
_mobThreshold.SetMobStateThreshold(disguise, health, MobState.Critical, thresholds);
|
||||||
|
_mobThreshold.SetMobStateThreshold(disguise, max, MobState.Dead, thresholds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add actions for controlling transform aspects
|
||||||
|
_actions.AddAction(disguise, proj.NoRotAction);
|
||||||
|
_actions.AddAction(disguise, proj.AnchorAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnToggleNoRot(Entity<ChameleonDisguiseComponent> ent, ref DisguiseToggleNoRotEvent args)
|
||||||
|
{
|
||||||
|
var xform = Transform(ent);
|
||||||
|
xform.NoLocalRotation = !xform.NoLocalRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnToggleAnchored(Entity<ChameleonDisguiseComponent> ent, ref DisguiseToggleAnchoredEvent args)
|
||||||
|
{
|
||||||
|
var uid = ent.Owner;
|
||||||
|
var xform = Transform(uid);
|
||||||
|
if (xform.Anchored)
|
||||||
|
_xform.Unanchor(uid, xform);
|
||||||
|
else
|
||||||
|
_xform.AnchorEntity((uid, xform));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Polymorph.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Component added to disguise entities.
|
||||||
|
/// Used by client to copy over appearance from the disguise's source entity.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
|
||||||
|
public sealed partial class ChameleonDisguiseComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The disguise source entity for copying the sprite.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public EntityUid SourceEntity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The source entity's prototype.
|
||||||
|
/// Used as a fallback if the source entity was deleted.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public EntProtoId? SourceProto;
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
using Content.Shared.Polymorph;
|
||||||
|
using Content.Shared.Polymorph.Systems;
|
||||||
|
using Content.Shared.Whitelist;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Polymorph.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A chameleon projector polymorphs you into a clicked entity, then polymorphs back when clicked on or destroyed.
|
||||||
|
/// This creates a new dummy polymorph entity and copies the appearance over.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, Access(typeof(SharedChameleonProjectorSystem))]
|
||||||
|
public sealed partial class ChameleonProjectorComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// If non-null, whitelist for valid entities to disguise as.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(required: true)]
|
||||||
|
public EntityWhitelist? Whitelist;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If non-null, blacklist that prevents entities from being used even if they are in the whitelist.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(required: true)]
|
||||||
|
public EntityWhitelist? Blacklist;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Polymorph configuration for the disguise entity.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(required: true)]
|
||||||
|
public PolymorphConfiguration Polymorph = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Action for disabling your disguise's rotation.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public EntProtoId NoRotAction = "ActionDisguiseNoRot";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Action for anchoring your disguise in place.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public EntProtoId AnchorAction = "ActionDisguiseAnchor";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Minimum health to give the disguise.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public float MinHealth = 1f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum health to give the disguise, health scales with mass.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public float MaxHealth = 100f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Popup shown to the user when they try to disguise as an invalid entity.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public LocId InvalidPopup = "chameleon-projector-invalid";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Popup shown to the user when they disguise as a valid entity.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public LocId SuccessPopup = "chameleon-projector-success";
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.Interaction;
|
||||||
|
using Content.Shared.Polymorph;
|
||||||
|
using Content.Shared.Polymorph.Components;
|
||||||
|
using Content.Shared.Popups;
|
||||||
|
using Robust.Shared.Serialization.Manager;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Content.Shared.Polymorph.Systems;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles whitelist/blacklist checking.
|
||||||
|
/// Actual polymorphing and deactivation is done serverside.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class SharedChameleonProjectorSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||||
|
[Dependency] private readonly ISerializationManager _serMan = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ChameleonProjectorComponent, AfterInteractEvent>(OnInteract);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInteract(Entity<ChameleonProjectorComponent> ent, ref AfterInteractEvent args)
|
||||||
|
{
|
||||||
|
if (!args.CanReach || args.Target is not {} target)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var user = args.User;
|
||||||
|
args.Handled = true;
|
||||||
|
|
||||||
|
if (IsInvalid(ent.Comp, target))
|
||||||
|
{
|
||||||
|
_popup.PopupClient(Loc.GetString(ent.Comp.InvalidPopup), target, user);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_popup.PopupClient(Loc.GetString(ent.Comp.SuccessPopup), target, user);
|
||||||
|
Disguise(ent.Comp, user, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if an entity cannot be used as a disguise.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsInvalid(ChameleonProjectorComponent comp, EntityUid target)
|
||||||
|
{
|
||||||
|
return (comp.Whitelist?.IsValid(target, EntityManager) == false)
|
||||||
|
|| (comp.Blacklist?.IsValid(target, EntityManager) == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// On server, polymorphs the user into an entity and sets up the disguise.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void Disguise(ChameleonProjectorComponent comp, EntityUid user, EntityUid entity)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copy a component from the source entity/prototype to the disguise entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This would probably be a good thing to add to engine in the future.
|
||||||
|
/// </remarks>
|
||||||
|
protected bool CopyComp<T>(Entity<ChameleonDisguiseComponent> ent) where T: Component, new()
|
||||||
|
{
|
||||||
|
if (!GetSrcComp<T>(ent.Comp, out var src))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// remove then re-add to prevent a funny
|
||||||
|
RemComp<T>(ent);
|
||||||
|
var dest = AddComp<T>(ent);
|
||||||
|
_serMan.CopyTo(src, ref dest, notNullableOverride: true);
|
||||||
|
Dirty(ent, dest);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to get a single component from the source entity/prototype.
|
||||||
|
/// </summary>
|
||||||
|
private bool GetSrcComp<T>(ChameleonDisguiseComponent comp, [NotNullWhen(true)] out T? src) where T: Component
|
||||||
|
{
|
||||||
|
src = null;
|
||||||
|
if (TryComp(comp.SourceEntity, out src))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (comp.SourceProto is not {} protoId)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!_proto.TryIndex<EntityPrototype>(protoId, out var proto))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return proto.TryGetComponent(out src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Action event for toggling transform NoRot on a disguise.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class DisguiseToggleNoRotEvent : InstantActionEvent
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Action event for toggling transform Anchored on a disguise.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class DisguiseToggleAnchoredEvent : InstantActionEvent
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
chameleon-projector-invalid = You can't disguise as that!
|
||||||
|
chameleon-projector-success = Projected new disguise.
|
||||||
@@ -367,6 +367,9 @@ uplink-slipocalypse-clustersoap-desc = Scatters arounds small pieces of syndicat
|
|||||||
uplink-mobcat-microbomb-name = SyndiCat
|
uplink-mobcat-microbomb-name = SyndiCat
|
||||||
uplink-mobcat-microbomb-desc = A hand cat equipped with a microbomb implant. Explodes when seriously injured. Can bite painfully
|
uplink-mobcat-microbomb-desc = A hand cat equipped with a microbomb implant. Explodes when seriously injured. Can bite painfully
|
||||||
|
|
||||||
|
uplink-chameleon-projector-name = Chameleon Projector
|
||||||
|
uplink-chameleon-projector-desc = Disappear in plain sight by creating a hologram of an item around you. Do not use this to play the game "Object Search".
|
||||||
|
|
||||||
# Pointless
|
# Pointless
|
||||||
uplink-revolver-cap-gun-name = Cap Gun
|
uplink-revolver-cap-gun-name = Cap Gun
|
||||||
uplink-revolver-cap-gun-desc = Looks almost like the real thing! Ages 8 and up.
|
uplink-revolver-cap-gun-desc = Looks almost like the real thing! Ages 8 and up.
|
||||||
|
|||||||
@@ -622,6 +622,16 @@
|
|||||||
categories:
|
categories:
|
||||||
- UplinkDeception
|
- UplinkDeception
|
||||||
|
|
||||||
|
- type: listing
|
||||||
|
id: UplinkChameleonProjector
|
||||||
|
name: uplink-chameleon-projector-name
|
||||||
|
description: uplink-chameleon-projector-desc
|
||||||
|
productEntity: ChameleonProjector
|
||||||
|
cost:
|
||||||
|
Telecrystal: 7
|
||||||
|
categories:
|
||||||
|
- UplinkDeception
|
||||||
|
|
||||||
- type: listing
|
- type: listing
|
||||||
id: UplinkHeadsetEncryptionKey
|
id: UplinkHeadsetEncryptionKey
|
||||||
name: uplink-encryption-key-name
|
name: uplink-encryption-key-name
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
- type: entity
|
||||||
|
parent: BaseItem
|
||||||
|
id: ChameleonProjector
|
||||||
|
name: chameleon projector
|
||||||
|
description: Holoparasite technology used to create a hard-light replica of any object around you. Disguise is destroyed when picked up or deactivated.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: /Textures/Objects/Devices/chameleon_projector.rsi
|
||||||
|
state: icon
|
||||||
|
- type: ChameleonProjector
|
||||||
|
whitelist:
|
||||||
|
components:
|
||||||
|
- Anchorable
|
||||||
|
- Item
|
||||||
|
blacklist:
|
||||||
|
components:
|
||||||
|
- ChameleonDisguise # no becoming kleiner
|
||||||
|
- InsideEntityStorage # no clark kent going in phone booth and becoming superman
|
||||||
|
- MindContainer # no
|
||||||
|
- Pda # PDAs currently make you invisible /!\
|
||||||
|
polymorph:
|
||||||
|
entity: ChameleonDisguise
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
noSpawn: true
|
||||||
|
parent: BaseMob
|
||||||
|
id: ChameleonDisguise
|
||||||
|
name: Urist McKleiner
|
||||||
|
components:
|
||||||
|
# this and the name/desc get replaced, this is just placeholder incase something goes wrong
|
||||||
|
- type: Sprite
|
||||||
|
sprite: /Textures/Mobs/Species/Human/parts.rsi
|
||||||
|
state: full
|
||||||
|
# so people can attempt to pick it up
|
||||||
|
- type: Item
|
||||||
|
# so it can take damage
|
||||||
|
# projector system sets health to be proportional to mass
|
||||||
|
- type: Damageable
|
||||||
|
- type: MobState
|
||||||
|
- type: MobThresholds
|
||||||
|
thresholds:
|
||||||
|
0: Alive
|
||||||
|
1: Critical
|
||||||
|
200: Dead
|
||||||
|
- type: MovementSpeedModifier
|
||||||
|
baseWalkSpeed: 1 # precise movement for the perfect spot
|
||||||
|
baseSprintSpeed: 5 # the jig is up
|
||||||
|
- type: ChameleonDisguise
|
||||||
|
|
||||||
|
# actions
|
||||||
|
- type: entity
|
||||||
|
noSpawn: true
|
||||||
|
id: ActionDisguiseNoRot
|
||||||
|
name: Toggle Rotation
|
||||||
|
description: Use this to prevent your disguise from rotating, making it easier to hide in some scenarios.
|
||||||
|
components:
|
||||||
|
- type: InstantAction
|
||||||
|
icon: Interface/VerbIcons/refresh.svg.192dpi.png
|
||||||
|
event: !type:DisguiseToggleNoRotEvent
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
noSpawn: true
|
||||||
|
id: ActionDisguiseAnchor
|
||||||
|
name: Toggle Anchored
|
||||||
|
description: For many objects you will want to be anchored to not be completely obvious.
|
||||||
|
components:
|
||||||
|
- type: InstantAction
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Tools/wrench.rsi
|
||||||
|
state: icon
|
||||||
|
event: !type:DisguiseToggleAnchoredEvent
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 716 B |
Binary file not shown.
|
After Width: | Height: | Size: 306 B |
Binary file not shown.
|
After Width: | Height: | Size: 316 B |
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "Taken from tgstation at ",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "icon",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.2,
|
||||||
|
0.2,
|
||||||
|
0.2,
|
||||||
|
0.2,
|
||||||
|
0.2,
|
||||||
|
0.2
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inhand-left",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inhand-right",
|
||||||
|
"directions": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user