magic bread wand (#17044)
Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
@@ -293,9 +293,16 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(component.TrashPrototype))
|
||||
EntityManager.QueueDeleteEntity(uid);
|
||||
var ev = new BeforeFullyEatenEvent
|
||||
{
|
||||
User = args.User
|
||||
};
|
||||
RaiseLocalEvent(uid, ev);
|
||||
if (ev.Cancelled)
|
||||
return;
|
||||
|
||||
if (string.IsNullOrEmpty(component.TrashPrototype))
|
||||
QueueDel(uid);
|
||||
else
|
||||
DeleteAndSpawnTrash(component, uid, args.User);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Server.Chemistry.Components.SolutionManager;
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Server.Nutrition;
|
||||
using Content.Server.Nutrition.Components;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Examine;
|
||||
@@ -51,12 +52,12 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EntityManager.TryGetComponent(usedItem, out UtensilComponent ? utensil) || (utensil.Types & UtensilType.Knife) == 0)
|
||||
if (!TryComp<UtensilComponent>(usedItem, out var utensil) || (utensil.Types & UtensilType.Knife) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var sliceUid = EntityManager.SpawnEntity(component.Slice, transform.Coordinates);
|
||||
var sliceUid = Spawn(component.Slice, transform.Coordinates);
|
||||
|
||||
var lostSolution = _solutionContainerSystem.SplitSolution(uid, solution,
|
||||
solution.Volume / FixedPoint2.New(component.Count));
|
||||
@@ -91,7 +92,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
// If someone makes food proto with 1 slice...
|
||||
if (component.Count < 1)
|
||||
{
|
||||
EntityManager.DeleteEntity(uid);
|
||||
DeleteFood(uid, user);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -99,7 +100,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
if (component.Count > 1)
|
||||
return true;
|
||||
|
||||
sliceUid = EntityManager.SpawnEntity(component.Slice, transform.Coordinates);
|
||||
sliceUid = Spawn(component.Slice, transform.Coordinates);
|
||||
|
||||
// Fill last slice with the rest of the solution
|
||||
FillSlice(sliceUid, solution);
|
||||
@@ -115,14 +116,26 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
xform.LocalRotation = 0;
|
||||
}
|
||||
|
||||
EntityManager.DeleteEntity(uid);
|
||||
DeleteFood(uid, user);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void DeleteFood(EntityUid uid, EntityUid user)
|
||||
{
|
||||
var ev = new BeforeFullySlicedEvent
|
||||
{
|
||||
User = user
|
||||
};
|
||||
RaiseLocalEvent(uid, ev);
|
||||
|
||||
if (!ev.Cancelled)
|
||||
Del(uid);
|
||||
}
|
||||
|
||||
private void FillSlice(EntityUid sliceUid, Solution solution)
|
||||
{
|
||||
// Replace all reagents on prototype not just copying poisons (example: slices of eaten pizza should have less nutrition)
|
||||
if (EntityManager.TryGetComponent<FoodComponent>(sliceUid, out var sliceFoodComp) &&
|
||||
if (TryComp<FoodComponent>(sliceUid, out var sliceFoodComp) &&
|
||||
_solutionContainerSystem.TryGetSolution(sliceUid, sliceFoodComp.SolutionName, out var itsSolution))
|
||||
{
|
||||
_solutionContainerSystem.RemoveAllSolution(sliceUid, itsSolution);
|
||||
@@ -135,9 +148,9 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
private void OnComponentStartup(EntityUid uid, SliceableFoodComponent component, ComponentStartup args)
|
||||
{
|
||||
component.Count = component.TotalCount;
|
||||
var foodComp = EntityManager.EnsureComponent<FoodComponent>(uid);
|
||||
var foodComp = EnsureComp<FoodComponent>(uid);
|
||||
|
||||
EntityManager.EnsureComponent<SolutionContainerManagerComponent>(uid);
|
||||
EnsureComp<SolutionContainerManagerComponent>(uid);
|
||||
_solutionContainerSystem.EnsureSolution(uid, foodComp.SolutionName);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,3 +10,27 @@ public sealed class IngestionAttemptEvent : CancellableEntityEventArgs
|
||||
/// </summary>
|
||||
public EntityUid? Blocker = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed at the food after finishing eating a food before it's deleted.
|
||||
/// Cancel this if you want to do something special before a food is deleted.
|
||||
/// </summary>
|
||||
public sealed class BeforeFullyEatenEvent : CancellableEntityEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// The person that ate the food.
|
||||
/// </summary>
|
||||
public EntityUid User;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed at the food being sliced before it's deleted.
|
||||
/// Cancel this if you want to do something special before a food is deleted.
|
||||
/// </summary>
|
||||
public sealed class BeforeFullySlicedEvent : CancellableEntityEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// The person slicing the food.
|
||||
/// </summary>
|
||||
public EntityUid User;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using Content.Server.Humanoid;
|
||||
using Content.Server.Inventory;
|
||||
using Content.Server.Mind.Commands;
|
||||
using Content.Server.Mind.Components;
|
||||
using Content.Server.Nutrition;
|
||||
using Content.Server.Polymorph.Components;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Actions.ActionTypes;
|
||||
@@ -41,7 +42,7 @@ namespace Content.Server.Polymorph.Systems
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
|
||||
private readonly ISawmill _saw = default!;
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -50,10 +51,14 @@ namespace Content.Server.Polymorph.Systems
|
||||
SubscribeLocalEvent<PolymorphableComponent, ComponentStartup>(OnStartup);
|
||||
SubscribeLocalEvent<PolymorphableComponent, PolymorphActionEvent>(OnPolymorphActionEvent);
|
||||
SubscribeLocalEvent<PolymorphedEntityComponent, ComponentStartup>(OnStartup);
|
||||
SubscribeLocalEvent<PolymorphedEntityComponent, BeforeFullyEatenEvent>(OnBeforeFullyEaten);
|
||||
SubscribeLocalEvent<PolymorphedEntityComponent, BeforeFullySlicedEvent>(OnBeforeFullySliced);
|
||||
SubscribeLocalEvent<PolymorphedEntityComponent, RevertPolymorphActionEvent>(OnRevertPolymorphActionEvent);
|
||||
|
||||
InitializeCollide();
|
||||
InitializeMap();
|
||||
|
||||
_sawmill = Logger.GetSawmill("polymorph");
|
||||
}
|
||||
|
||||
private void OnStartup(EntityUid uid, PolymorphableComponent component, ComponentStartup args)
|
||||
@@ -82,7 +87,7 @@ namespace Content.Server.Polymorph.Systems
|
||||
if (!_proto.TryIndex(component.Prototype, out PolymorphPrototype? proto))
|
||||
{
|
||||
// warning instead of error because of the all-comps one entity test.
|
||||
Logger.Warning($"{nameof(PolymorphSystem)} encountered an improperly set up polymorph component while initializing. Entity {ToPrettyString(uid)}. Prototype: {component.Prototype}");
|
||||
_sawmill.Warning($"{nameof(PolymorphSystem)} encountered an improperly set up polymorph component while initializing. Entity {ToPrettyString(uid)}. Prototype: {component.Prototype}");
|
||||
RemCompDeferred(uid, component);
|
||||
return;
|
||||
}
|
||||
@@ -102,6 +107,36 @@ namespace Content.Server.Polymorph.Systems
|
||||
_actions.AddAction(uid, act, null);
|
||||
}
|
||||
|
||||
private void OnBeforeFullyEaten(EntityUid uid, PolymorphedEntityComponent comp, BeforeFullyEatenEvent args)
|
||||
{
|
||||
if (!_proto.TryIndex<PolymorphPrototype>(comp.Prototype, out var proto))
|
||||
{
|
||||
_sawmill.Error("Invalid polymorph prototype {comp.Prototype}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (proto.RevertOnEat)
|
||||
{
|
||||
args.Cancel();
|
||||
Revert(uid, comp);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBeforeFullySliced(EntityUid uid, PolymorphedEntityComponent comp, BeforeFullySlicedEvent args)
|
||||
{
|
||||
if (!_proto.TryIndex<PolymorphPrototype>(comp.Prototype, out var proto))
|
||||
{
|
||||
_sawmill.Error("Invalid polymorph prototype {comp.Prototype}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (proto.RevertOnEat)
|
||||
{
|
||||
args.Cancel();
|
||||
Revert(uid, comp);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Polymorphs the target entity into the specific polymorph prototype
|
||||
/// </summary>
|
||||
@@ -111,7 +146,7 @@ namespace Content.Server.Polymorph.Systems
|
||||
{
|
||||
if (!_proto.TryIndex<PolymorphPrototype>(id, out var proto))
|
||||
{
|
||||
_saw.Error("Invalid polymorph prototype");
|
||||
_sawmill.Error("Invalid polymorph prototype {id}");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -225,7 +260,7 @@ namespace Content.Server.Polymorph.Systems
|
||||
|
||||
if (!_proto.TryIndex(component.Prototype, out PolymorphPrototype? proto))
|
||||
{
|
||||
Logger.Error($"{nameof(PolymorphSystem)} encountered an improperly initialized polymorph component while reverting. Entity {ToPrettyString(uid)}. Prototype: {component.Prototype}");
|
||||
_sawmill.Error($"{nameof(PolymorphSystem)} encountered an improperly initialized polymorph component while reverting. Entity {ToPrettyString(uid)}. Prototype: {component.Prototype}");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -236,9 +271,6 @@ namespace Content.Server.Polymorph.Systems
|
||||
parentXform.Coordinates = uidXform.Coordinates;
|
||||
parentXform.LocalRotation = uidXform.LocalRotation;
|
||||
|
||||
if (_container.TryGetContainingContainer(uid, out var cont))
|
||||
cont.Insert(component.Parent);
|
||||
|
||||
if (proto.TransferDamage &&
|
||||
TryComp<DamageableComponent>(parent, out var damageParent) &&
|
||||
_mobThreshold.GetScaledDamage(uid, parent, out var damage) &&
|
||||
@@ -277,6 +309,9 @@ namespace Content.Server.Polymorph.Systems
|
||||
mind.Mind.TransferTo(parent);
|
||||
}
|
||||
|
||||
// if an item polymorph was picked up, put it back down after reverting
|
||||
Transform(parent).AttachToGridOrMap();
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("polymorph-revert-popup-generic",
|
||||
("parent", Identity.Entity(uid, EntityManager)),
|
||||
("child", Identity.Entity(parent, EntityManager))),
|
||||
@@ -293,7 +328,7 @@ namespace Content.Server.Polymorph.Systems
|
||||
{
|
||||
if (!_proto.TryIndex<PolymorphPrototype>(id, out var polyproto))
|
||||
{
|
||||
_saw.Error("Invalid polymorph prototype");
|
||||
_sawmill.Error("Invalid polymorph prototype");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -335,27 +370,32 @@ namespace Content.Server.Polymorph.Systems
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
foreach (var comp in EntityQuery<PolymorphedEntityComponent>())
|
||||
var query = EntityQueryEnumerator<PolymorphedEntityComponent>();
|
||||
while (query.MoveNext(out var uid, out var comp))
|
||||
{
|
||||
comp.Time += frameTime;
|
||||
var ent = comp.Owner;
|
||||
|
||||
if (!_proto.TryIndex(comp.Prototype, out PolymorphPrototype? proto))
|
||||
{
|
||||
Logger.Error($"{nameof(PolymorphSystem)} encountered an improperly initialized polymorph component while updating. Entity {ToPrettyString(ent)}. Prototype: {comp.Prototype}");
|
||||
RemCompDeferred(ent, comp);
|
||||
_sawmill.Error($"{nameof(PolymorphSystem)} encountered an improperly initialized polymorph component while updating. Entity {ToPrettyString(uid)}. Prototype: {comp.Prototype}");
|
||||
RemCompDeferred(uid, comp);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(proto.Duration != null && comp.Time >= proto.Duration)
|
||||
Revert(ent, comp);
|
||||
if (proto.Duration != null && comp.Time >= proto.Duration)
|
||||
{
|
||||
Revert(uid, comp);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!TryComp<MobStateComponent>(ent, out var mob))
|
||||
if (!TryComp<MobStateComponent>(uid, out var mob))
|
||||
continue;
|
||||
|
||||
if (proto.RevertOnDeath && _mobState.IsDead(ent, mob) ||
|
||||
proto.RevertOnCrit && _mobState.IsIncapacitated(ent, mob))
|
||||
Revert(ent, comp);
|
||||
if (proto.RevertOnDeath && _mobState.IsDead(uid, mob) ||
|
||||
proto.RevertOnCrit && _mobState.IsIncapacitated(uid, mob))
|
||||
{
|
||||
Revert(uid, comp);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateCollide();
|
||||
|
||||
@@ -89,6 +89,12 @@ namespace Content.Shared.Polymorph
|
||||
[DataField("revertOnDeath", serverOnly: true)]
|
||||
public bool RevertOnDeath = true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the polymorph reverts when the entity is eaten or fully sliced.
|
||||
/// </summary>
|
||||
[DataField("revertOnEat", serverOnly: true)]
|
||||
public bool RevertOnEat = false;
|
||||
|
||||
[DataField("allowRepeatedMorphs", serverOnly: true)]
|
||||
public bool AllowRepeatedMorphs = false;
|
||||
}
|
||||
|
||||
@@ -105,3 +105,14 @@
|
||||
proto: ProjectilePolyboltCluwne
|
||||
capacity: 3
|
||||
count: 3
|
||||
|
||||
- type: entity
|
||||
parent: WeaponWandPolymorphBase
|
||||
id: WeaponWandPolymorphBread
|
||||
name: magic bread wand
|
||||
description: Turn all your friends into bread! Your boss! Your enemies! Your dog! Make everything bread!
|
||||
components:
|
||||
- type: BasicEntityAmmoProvider
|
||||
proto: ProjectilePolyboltBread
|
||||
capacity: 10
|
||||
count: 10
|
||||
|
||||
@@ -141,3 +141,15 @@
|
||||
Cold: 20
|
||||
Structural: 40
|
||||
|
||||
- type: entity
|
||||
parent: ProjectilePolyboltBase
|
||||
id: ProjectilePolyboltBread
|
||||
name: bread polybolt
|
||||
description: Nooo, I don't wanna be bread!
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: PolymorphOnCollide
|
||||
polymorph: BreadMorph
|
||||
whitelist:
|
||||
components:
|
||||
- Body
|
||||
|
||||
@@ -83,3 +83,14 @@
|
||||
transferName: true
|
||||
revertOnCrit: false
|
||||
revertOnDeath: false
|
||||
|
||||
- type: polymorph
|
||||
id: BreadMorph
|
||||
entity: FoodBreadPlain
|
||||
forced: true
|
||||
inventory: None
|
||||
transferName: false
|
||||
transferDamage: true
|
||||
revertOnCrit: false
|
||||
revertOnDeath: true
|
||||
revertOnEat: true
|
||||
|
||||
Reference in New Issue
Block a user