Chameleon Projector Battery, Price Decrease (#42271)

* init

* fuck using

* glowup

* unused

* meta

* whuh

* review

* tests

* Update SharedChameleonProjectorSystem.cs
This commit is contained in:
ScarKy0
2026-01-07 06:51:44 +01:00
committed by GitHub
parent 4ed0d37efc
commit 590dc948ee
9 changed files with 116 additions and 19 deletions

View File

@@ -3,5 +3,6 @@ namespace Content.Client.Power;
/// Remains in use by portable scrubbers and lathes.
public enum PowerDeviceVisualLayers : byte
{
Powered
Powered,
Charging
}

View File

@@ -14,6 +14,8 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager;
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Damage.Systems;
using Content.Shared.Item.ItemToggle;
using Content.Shared.Item.ItemToggle.Components;
namespace Content.Shared.Polymorph.Systems;
@@ -34,6 +36,7 @@ public abstract class SharedChameleonProjectorSystem : EntitySystem
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SharedTransformSystem _xform = default!;
[Dependency] private readonly ItemToggleSystem _toggle = default!;
public override void Initialize()
{
@@ -53,6 +56,7 @@ public abstract class SharedChameleonProjectorSystem : EntitySystem
SubscribeLocalEvent<ChameleonProjectorComponent, HandDeselectedEvent>(OnDeselected);
SubscribeLocalEvent<ChameleonProjectorComponent, GotUnequippedHandEvent>(OnUnequipped);
SubscribeLocalEvent<ChameleonProjectorComponent, ComponentShutdown>(OnProjectorShutdown);
SubscribeLocalEvent<ChameleonProjectorComponent, ItemToggledEvent>(OnProjectorToggled);
}
#region Disguise entity
@@ -105,6 +109,18 @@ public abstract class SharedChameleonProjectorSystem : EntitySystem
TryDisguise(ent, args.User, target);
}
private void OnProjectorToggled(Entity<ChameleonProjectorComponent> ent, ref ItemToggledEvent args)
{
if (args.Activated)
return;
if (ent.Comp.Disguised == null)
return;
// We don't toggle here as this is only called when we subscribe to being toggled off.
TryReveal(ent.Comp.Disguised.Value);
}
private void OnGetVerbs(Entity<ChameleonProjectorComponent> ent, ref GetVerbsEvent<UtilityVerb> args)
{
if (!args.CanAccess)
@@ -136,6 +152,10 @@ public abstract class SharedChameleonProjectorSystem : EntitySystem
return false;
}
// We do a TryComp, so if the item has variations without ItemToggle, they can still be used just fine.
if (TryComp<ItemToggleComponent>(ent.Owner, out var itemToggle) && !_toggle.TryActivate((ent.Owner, itemToggle), user))
return false;
_popup.PopupClient(Loc.GetString("chameleon-projector-success"), target, user);
Disguise(ent, user, target);
return true;
@@ -206,7 +226,8 @@ public abstract class SharedChameleonProjectorSystem : EntitySystem
return;
// reveal first to allow quick switching
TryReveal(user);
if (ent.Comp.Disguised != null)
ClearDisguise(ent, ent.Comp.Disguised.Value);
// add actions for controlling transform aspects
_actions.AddAction(user, ref proj.NoRotActionEntity, proj.NoRotAction, container: ent);
@@ -216,7 +237,7 @@ public abstract class SharedChameleonProjectorSystem : EntitySystem
var disguise = SpawnAttachedTo(proj.DisguiseProto, user.ToCoordinates());
var disguised = AddComp<ChameleonDisguisedComponent>(user);
var disguised = EnsureComp<ChameleonDisguisedComponent>(user);
disguised.Disguise = disguise;
Dirty(user, disguised);
@@ -246,21 +267,38 @@ public abstract class SharedChameleonProjectorSystem : EntitySystem
if (!Resolve(ent, ref ent.Comp, false))
return false;
if (TryComp<ChameleonDisguiseComponent>(ent.Comp.Disguise, out var disguise)
&& TryComp<ChameleonProjectorComponent>(disguise.Projector, out var proj))
{
proj.Disguised = null;
}
if (!TryComp<ChameleonDisguiseComponent>(ent.Comp.Disguise, out var disguise)
|| !TryComp<ChameleonProjectorComponent>(disguise.Projector, out var proj))
return false;
var xform = Transform(ent);
xform.NoLocalRotation = false;
_xform.Unanchor(ent, xform);
ClearDisguise((disguise.Projector, proj), ent);
_toggle.TryDeactivate(disguise.Projector);
Del(ent.Comp.Disguise);
RemComp<ChameleonDisguisedComponent>(ent);
return true;
}
/// <summary>
/// Clears the disguise for the projector, allowing the user to immediately disguise again.
/// </summary>
/// <param name="ent">The entity for which to clear the disguise</param>
/// <param name="disguised">The disguised entity.</param>
private void ClearDisguise(Entity<ChameleonProjectorComponent> ent, Entity<ChameleonDisguisedComponent?> disguised)
{
if (!Resolve(disguised, ref disguised.Comp, false))
return;
if (ent.Comp.Disguised == null)
return;
var xform = Transform(ent.Comp.Disguised.Value);
xform.NoLocalRotation = false;
_xform.Unanchor(disguised, xform);
ent.Comp.Disguised = null;
Del(disguised.Comp.Disguise);
}
/// <summary>
/// Reveal a projector's user, if any.
/// </summary>

View File

@@ -847,9 +847,9 @@
productEntity: ChameleonProjector
discountCategory: rareDiscounts
discountDownTo:
Telecrystal: 4
Telecrystal: 2
cost:
Telecrystal: 7
Telecrystal: 3
categories:
- UplinkDeception

View File

@@ -1,12 +1,18 @@
- type: entity
parent: [BaseItem, BaseSyndicateContraband]
id: ChameleonProjector
id: ChameleonProjectorNoBattery
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
layers:
- state: icon
- state: powered
map: [ "enum.PowerDeviceVisualLayers.Powered" ]
- state: decharging
map: [ "enum.PowerDeviceVisualLayers.Charging" ]
visible: false
- type: ChameleonProjector
whitelist:
components:
@@ -29,6 +35,44 @@
- type: StaticPrice
price: 5000
- type: entity
parent: ChameleonProjectorNoBattery
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.
suffix: Battery
components:
- type: Appearance
- type: GenericVisualizer
visuals:
enum.BatteryVisuals.State:
enum.PowerDeviceVisualLayers.Powered:
Full: { visible: true }
Neither: { visible: true }
Empty: { visible: false }
enum.BatteryVisuals.Charging:
enum.PowerDeviceVisualLayers.Charging:
Charging: { visible: false }
Decharging: { visible: true }
Constant: { visible: false }
- type: BatteryVisuals
- type: ContainerContainer
containers:
cell_slot: !type:ContainerSlot
- type: ItemSlots
slots:
cell_slot:
name: power-cell-slot-component-slot-name-default
startingItem: PowerCellMedium
- type: PowerCellSlot
cellSlotId: cell_slot
- type: PowerCellDraw
drawRate: 4 # About 3 minutes with a medium cell.
- type: ToggleCellDraw
- type: ItemToggle
onActivate: false
onUse: false
- type: entity
categories: [ HideSpawnMenu ]
id: ChameleonDisguise

View File

@@ -1655,7 +1655,7 @@
- state: icon-xenoborg-projector
- type: ItemBorgModule
hands:
- item: ChameleonProjector
- item: ChameleonProjectorNoBattery
- type: BorgModuleIcon
icon: { sprite: Interface/Actions/actions_borg.rsi, state: xenoborg-projector-module }

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 716 B

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -1,14 +1,17 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/71a1fee2f13730adee5302d34bfa0f0262314d63, Inhands by TiniestShark (github)",
"copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/71a1fee2f13730adee5302d34bfa0f0262314d63, Inhands by TiniestShark (github), decharging, icon and powered seperated by ScarKy0(Github)",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon",
"name": "icon"
},
{
"name": "powered",
"delays": [
[
0.2,
@@ -20,6 +23,17 @@
]
]
},
{
"name": "decharging",
"delays": [
[
0.2,
0.2,
0.2,
0.2
]
]
},
{
"name": "inhand-left",
"directions": 4

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB