magic bread wand (#17044)

Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
deltanedas
2023-06-03 19:08:52 +00:00
committed by GitHub
parent b4ecd61438
commit 2bef7bfa38
8 changed files with 152 additions and 28 deletions

View File

@@ -293,9 +293,16 @@ namespace Content.Server.Nutrition.EntitySystems
return; return;
} }
if (string.IsNullOrEmpty(component.TrashPrototype)) var ev = new BeforeFullyEatenEvent
EntityManager.QueueDeleteEntity(uid); {
User = args.User
};
RaiseLocalEvent(uid, ev);
if (ev.Cancelled)
return;
if (string.IsNullOrEmpty(component.TrashPrototype))
QueueDel(uid);
else else
DeleteAndSpawnTrash(component, uid, args.User); DeleteAndSpawnTrash(component, uid, args.User);
} }

View File

@@ -1,5 +1,6 @@
using Content.Server.Chemistry.Components.SolutionManager; using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.EntitySystems;
using Content.Server.Nutrition;
using Content.Server.Nutrition.Components; using Content.Server.Nutrition.Components;
using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components;
using Content.Shared.Examine; using Content.Shared.Examine;
@@ -51,12 +52,12 @@ namespace Content.Server.Nutrition.EntitySystems
return false; 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; return false;
} }
var sliceUid = EntityManager.SpawnEntity(component.Slice, transform.Coordinates); var sliceUid = Spawn(component.Slice, transform.Coordinates);
var lostSolution = _solutionContainerSystem.SplitSolution(uid, solution, var lostSolution = _solutionContainerSystem.SplitSolution(uid, solution,
solution.Volume / FixedPoint2.New(component.Count)); solution.Volume / FixedPoint2.New(component.Count));
@@ -91,7 +92,7 @@ namespace Content.Server.Nutrition.EntitySystems
// If someone makes food proto with 1 slice... // If someone makes food proto with 1 slice...
if (component.Count < 1) if (component.Count < 1)
{ {
EntityManager.DeleteEntity(uid); DeleteFood(uid, user);
return true; return true;
} }
@@ -99,7 +100,7 @@ namespace Content.Server.Nutrition.EntitySystems
if (component.Count > 1) if (component.Count > 1)
return true; return true;
sliceUid = EntityManager.SpawnEntity(component.Slice, transform.Coordinates); sliceUid = Spawn(component.Slice, transform.Coordinates);
// Fill last slice with the rest of the solution // Fill last slice with the rest of the solution
FillSlice(sliceUid, solution); FillSlice(sliceUid, solution);
@@ -115,14 +116,26 @@ namespace Content.Server.Nutrition.EntitySystems
xform.LocalRotation = 0; xform.LocalRotation = 0;
} }
EntityManager.DeleteEntity(uid); DeleteFood(uid, user);
return true; 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) 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) // 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.TryGetSolution(sliceUid, sliceFoodComp.SolutionName, out var itsSolution))
{ {
_solutionContainerSystem.RemoveAllSolution(sliceUid, itsSolution); _solutionContainerSystem.RemoveAllSolution(sliceUid, itsSolution);
@@ -135,9 +148,9 @@ namespace Content.Server.Nutrition.EntitySystems
private void OnComponentStartup(EntityUid uid, SliceableFoodComponent component, ComponentStartup args) private void OnComponentStartup(EntityUid uid, SliceableFoodComponent component, ComponentStartup args)
{ {
component.Count = component.TotalCount; 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); _solutionContainerSystem.EnsureSolution(uid, foodComp.SolutionName);
} }

View File

@@ -10,3 +10,27 @@ public sealed class IngestionAttemptEvent : CancellableEntityEventArgs
/// </summary> /// </summary>
public EntityUid? Blocker = null; 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;
}

View File

@@ -3,6 +3,7 @@ using Content.Server.Humanoid;
using Content.Server.Inventory; using Content.Server.Inventory;
using Content.Server.Mind.Commands; using Content.Server.Mind.Commands;
using Content.Server.Mind.Components; using Content.Server.Mind.Components;
using Content.Server.Nutrition;
using Content.Server.Polymorph.Components; using Content.Server.Polymorph.Components;
using Content.Shared.Actions; using Content.Shared.Actions;
using Content.Shared.Actions.ActionTypes; using Content.Shared.Actions.ActionTypes;
@@ -41,7 +42,7 @@ namespace Content.Server.Polymorph.Systems
[Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly TransformSystem _transform = default!; [Dependency] private readonly TransformSystem _transform = default!;
private readonly ISawmill _saw = default!; private ISawmill _sawmill = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -50,10 +51,14 @@ namespace Content.Server.Polymorph.Systems
SubscribeLocalEvent<PolymorphableComponent, ComponentStartup>(OnStartup); SubscribeLocalEvent<PolymorphableComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<PolymorphableComponent, PolymorphActionEvent>(OnPolymorphActionEvent); SubscribeLocalEvent<PolymorphableComponent, PolymorphActionEvent>(OnPolymorphActionEvent);
SubscribeLocalEvent<PolymorphedEntityComponent, ComponentStartup>(OnStartup); SubscribeLocalEvent<PolymorphedEntityComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<PolymorphedEntityComponent, BeforeFullyEatenEvent>(OnBeforeFullyEaten);
SubscribeLocalEvent<PolymorphedEntityComponent, BeforeFullySlicedEvent>(OnBeforeFullySliced);
SubscribeLocalEvent<PolymorphedEntityComponent, RevertPolymorphActionEvent>(OnRevertPolymorphActionEvent); SubscribeLocalEvent<PolymorphedEntityComponent, RevertPolymorphActionEvent>(OnRevertPolymorphActionEvent);
InitializeCollide(); InitializeCollide();
InitializeMap(); InitializeMap();
_sawmill = Logger.GetSawmill("polymorph");
} }
private void OnStartup(EntityUid uid, PolymorphableComponent component, ComponentStartup args) 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)) if (!_proto.TryIndex(component.Prototype, out PolymorphPrototype? proto))
{ {
// warning instead of error because of the all-comps one entity test. // 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); RemCompDeferred(uid, component);
return; return;
} }
@@ -102,6 +107,36 @@ namespace Content.Server.Polymorph.Systems
_actions.AddAction(uid, act, null); _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> /// <summary>
/// Polymorphs the target entity into the specific polymorph prototype /// Polymorphs the target entity into the specific polymorph prototype
/// </summary> /// </summary>
@@ -111,7 +146,7 @@ namespace Content.Server.Polymorph.Systems
{ {
if (!_proto.TryIndex<PolymorphPrototype>(id, out var proto)) if (!_proto.TryIndex<PolymorphPrototype>(id, out var proto))
{ {
_saw.Error("Invalid polymorph prototype"); _sawmill.Error("Invalid polymorph prototype {id}");
return null; return null;
} }
@@ -225,7 +260,7 @@ namespace Content.Server.Polymorph.Systems
if (!_proto.TryIndex(component.Prototype, out PolymorphPrototype? proto)) 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; return;
} }
@@ -236,9 +271,6 @@ namespace Content.Server.Polymorph.Systems
parentXform.Coordinates = uidXform.Coordinates; parentXform.Coordinates = uidXform.Coordinates;
parentXform.LocalRotation = uidXform.LocalRotation; parentXform.LocalRotation = uidXform.LocalRotation;
if (_container.TryGetContainingContainer(uid, out var cont))
cont.Insert(component.Parent);
if (proto.TransferDamage && if (proto.TransferDamage &&
TryComp<DamageableComponent>(parent, out var damageParent) && TryComp<DamageableComponent>(parent, out var damageParent) &&
_mobThreshold.GetScaledDamage(uid, parent, out var damage) && _mobThreshold.GetScaledDamage(uid, parent, out var damage) &&
@@ -277,6 +309,9 @@ namespace Content.Server.Polymorph.Systems
mind.Mind.TransferTo(parent); 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", _popup.PopupEntity(Loc.GetString("polymorph-revert-popup-generic",
("parent", Identity.Entity(uid, EntityManager)), ("parent", Identity.Entity(uid, EntityManager)),
("child", Identity.Entity(parent, EntityManager))), ("child", Identity.Entity(parent, EntityManager))),
@@ -293,7 +328,7 @@ namespace Content.Server.Polymorph.Systems
{ {
if (!_proto.TryIndex<PolymorphPrototype>(id, out var polyproto)) if (!_proto.TryIndex<PolymorphPrototype>(id, out var polyproto))
{ {
_saw.Error("Invalid polymorph prototype"); _sawmill.Error("Invalid polymorph prototype");
return; return;
} }
@@ -335,27 +370,32 @@ namespace Content.Server.Polymorph.Systems
{ {
base.Update(frameTime); 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; comp.Time += frameTime;
var ent = comp.Owner;
if (!_proto.TryIndex(comp.Prototype, out PolymorphPrototype? proto)) 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}"); _sawmill.Error($"{nameof(PolymorphSystem)} encountered an improperly initialized polymorph component while updating. Entity {ToPrettyString(uid)}. Prototype: {comp.Prototype}");
RemCompDeferred(ent, comp); RemCompDeferred(uid, comp);
continue; continue;
} }
if(proto.Duration != null && comp.Time >= proto.Duration) if (proto.Duration != null && comp.Time >= proto.Duration)
Revert(ent, comp); {
Revert(uid, comp);
continue;
}
if (!TryComp<MobStateComponent>(ent, out var mob)) if (!TryComp<MobStateComponent>(uid, out var mob))
continue; continue;
if (proto.RevertOnDeath && _mobState.IsDead(ent, mob) || if (proto.RevertOnDeath && _mobState.IsDead(uid, mob) ||
proto.RevertOnCrit && _mobState.IsIncapacitated(ent, mob)) proto.RevertOnCrit && _mobState.IsIncapacitated(uid, mob))
Revert(ent, comp); {
Revert(uid, comp);
}
} }
UpdateCollide(); UpdateCollide();

View File

@@ -89,6 +89,12 @@ namespace Content.Shared.Polymorph
[DataField("revertOnDeath", serverOnly: true)] [DataField("revertOnDeath", serverOnly: true)]
public bool RevertOnDeath = 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)] [DataField("allowRepeatedMorphs", serverOnly: true)]
public bool AllowRepeatedMorphs = false; public bool AllowRepeatedMorphs = false;
} }

View File

@@ -105,3 +105,14 @@
proto: ProjectilePolyboltCluwne proto: ProjectilePolyboltCluwne
capacity: 3 capacity: 3
count: 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

View File

@@ -141,3 +141,15 @@
Cold: 20 Cold: 20
Structural: 40 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

View File

@@ -83,3 +83,14 @@
transferName: true transferName: true
revertOnCrit: false revertOnCrit: false
revertOnDeath: false revertOnDeath: false
- type: polymorph
id: BreadMorph
entity: FoodBreadPlain
forced: true
inventory: None
transferName: false
transferDamage: true
revertOnCrit: false
revertOnDeath: true
revertOnEat: true