Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#TajaranLivesMatter, часть первая: Диета #267

Merged
merged 17 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Content.Server/Body/Components/StomachComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ public sealed partial class StomachComponent : Component
[DataField]
public EntityWhitelist? SpecialDigestible = null;

/// <summary>
/// Добавлено LostParadise.
/// Data responsible to describe what foods this stomach is incapable of processing efficiently.
/// </summary>
[DataField("poorlyDigestibleFood")]
public PoorlyDigestibleFood? LPP_PoorlyDigestibleFood = null;
Comment on lines +50 to +55
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Рассмотрите улучшение документации и согласованности именования.

Новое свойство LPP_PoorlyDigestibleFood добавляет функциональность для отслеживания плохо усваиваемой пищи. Однако есть несколько моментов, которые стоит рассмотреть:

  1. XML-документация могла бы быть более подробной. Рекомендуется добавить информацию о том, как именно используется это свойство и какие типы данных оно может содержать.

  2. Префикс "LPP_" в имени свойства отличается от стиля именования других свойств в классе. Убедитесь, что это соответствует принятым в проекте соглашениям об именовании.

  3. Имя в атрибуте DataField ("poorlyDigestibleFood") отличается от имени свойства. Хотя это может быть намеренным для целей сериализации, убедитесь, что это не вызовет путаницы при использовании.

Предлагаю следующие улучшения:

 /// <summary>
-///     Добавлено LostParadise.
-///     Data responsible to describe what foods this stomach is incapable of processing efficiently.
+///     Описывает типы пищи, которые этот желудок не может эффективно переваривать.
+///     Используется для определения пониженной питательной ценности и возможных побочных эффектов.
 /// </summary>
 [DataField("poorlyDigestibleFood")]
-public PoorlyDigestibleFood? LPP_PoorlyDigestibleFood = null;
+public PoorlyDigestibleFood? PoorlyDigestibleFood = null;

Эти изменения улучшат читаемость кода и сделают его более согласованным с остальной частью класса.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// <summary>
/// Добавлено LostParadise.
/// Data responsible to describe what foods this stomach is incapable of processing efficiently.
/// </summary>
[DataField("poorlyDigestibleFood")]
public PoorlyDigestibleFood? LPP_PoorlyDigestibleFood = null;
/// <summary>
/// Описывает типы пищи, которые этот желудок не может эффективно переваривать.
/// Используется для определения пониженной питательной ценности и возможных побочных эффектов.
/// </summary>
[DataField("poorlyDigestibleFood")]
public PoorlyDigestibleFood? PoorlyDigestibleFood = null;


/// <summary>
/// Used to track how long each reagent has been in the stomach
/// </summary>
Expand Down
5 changes: 5 additions & 0 deletions Content.Server/Nutrition/EntitySystems/FoodSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,11 @@ private void OnDoAfter(Entity<FoodComponent> entity, ref ConsumeDoAfterEvent arg
}

_reaction.DoEntityReaction(args.Target.Value, solution, ReactionMethod.Ingestion);

// Добавлено LostParadise.
Evgencheg marked this conversation as resolved.
Show resolved Hide resolved
if (stomachToUse.LPP_PoorlyDigestibleFood?.AffectsFood(entity, EntityManager) == true)
Evgencheg marked this conversation as resolved.
Show resolved Hide resolved
split = stomachToUse.LPP_PoorlyDigestibleFood.ModifySolution(split);

_stomach.TryTransferSolution(stomachToUse.Owner, split, stomachToUse);

var flavors = args.FlavorMessage;
Expand Down
112 changes: 112 additions & 0 deletions Content.Server/_LostParadise/CarnivoresDiet/AccumulateReagent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using Content.Server.Body.Components;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;

namespace Content.Server.Chemistry.ReagentEffects
{
// This class is basically copied from the sealed class AdjustReagent, but compensates a reagent's metabolism rates when adjusting its levels.
// Was introduced in order to make theobromine accumulate faster than it metabolises.
// While quite kludgy, it is still much safer and cleaner alternative to actively preventing the metabolism system from processing theobromine while it's still in the system.

// TL;DR Это костыль, который тупо добавляет столько же реагента, сколько должно впитаться за данный тик.
// Решение сомнительное, но оно гораздо чище, чем лезть в код метаболирования и добавлять туда группу-исключение с проверкой на наличие реагента в кровеносной системе.

[UsedImplicitly]
public sealed partial class AccumulateReagent : ReagentEffect
Evgencheg marked this conversation as resolved.
Show resolved Hide resolved
{
/// <summary>
/// The reagent ID to accumulate. Only one of this and <see cref="Group"/> should be active.
/// </summary>
[DataField(customTypeSerializer: typeof(PrototypeIdSerializer<ReagentPrototype>), required: true)]
public string? Reagent;

/// <summary>
/// Checks if the target has something that already adds the target reagent
/// </summary>
public bool ContainsPositiveAdjustEffect(IPrototypeManager prototypeMan, Solution solution, List<MetabolismGroupEntry> groups)
{
foreach (var quantity in solution.Contents)
{
var reagent = quantity.Reagent.Prototype;
if (reagent == Reagent)
continue;

if (!prototypeMan.TryIndex(reagent, out ReagentPrototype? reagentProto))
continue;

if (reagentProto?.Metabolisms == null)
continue;

// Ideally we should iterate over the body's MetabolismGroupEntry list.
// But I have no idea why there's no Drink in its .MetabolismGroups property and how to fetch that.
// So it will stay like this for now, but might cause unintended theobromine accumulation in some *very* unlikely and specific scenarios.
foreach (var reagentEffectsEntry in reagentProto.Metabolisms.Values)
Evgencheg marked this conversation as resolved.
Show resolved Hide resolved
{
foreach (var effect in reagentEffectsEntry.Effects)
{
if (effect is not AdjustReagent adjustReagent)
continue;

if (adjustReagent.Reagent == Reagent)
return true;
}
}
}

return false;
}

public override void Effect(ReagentEffectArgs args)
{
// Source is where Theobromine is currently coming from
if (args.Source == null)
return;

if (Reagent == null)
return;

var prototypeMan = IoCManager.Resolve<IPrototypeManager>();
prototypeMan.TryIndex(Reagent, out ReagentPrototype? reagentProto);

args.EntityManager.TryGetComponent(args.OrganEntity, out MetabolizerComponent? metabolizer);

if (metabolizer?.MetabolismGroups is not List<MetabolismGroupEntry> groups)
return;

if (!ContainsPositiveAdjustEffect(prototypeMan, args.Source, groups))
return;

if (reagentProto?.Metabolisms == null)
return;

FixedPoint2 totalCompensationRate = 0;
foreach (var group in groups)
{
// Normally, the rate should only be processed once since a reagent usually only has one group.
if (!reagentProto.Metabolisms.TryGetValue(group.Id, out var reagentEffectsEntry))
continue;

var groupRate = reagentEffectsEntry.MetabolismRate * group.MetabolismRateModifier;
totalCompensationRate += groupRate;
}

// amount *= args.Scale;
Evgencheg marked this conversation as resolved.
Show resolved Hide resolved
args.Source.AddReagent(Reagent, totalCompensationRate);
}

protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
if (Reagent != null && prototype.TryIndex(Reagent, out ReagentPrototype? reagentProto))
{
return Loc.GetString("reagent-effect-guidebook-accumulate-reagent-reagent",
("reagent", reagentProto.LocalizedName));
}

throw new NotImplementedException();
Evgencheg marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
92 changes: 92 additions & 0 deletions Content.Server/_LostParadise/CarnivoresDiet/PoorlyDigestible.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using Content.Server.Nutrition.Components;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using Content.Shared.Tag;
using Content.Shared.Whitelist;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Content.Server.Body.Components
{
[DataDefinition]
public sealed partial class PoorlyDigestibleFood
{
/// <summary>
/// Reagents that get multiplied by the Factor field.
/// </summary>
[DataField("reducedReagents")]
public List<string>? ReducedReagents = null;

/// <summary>
/// Food containing at least one of these tags is affected as long as it doesn't hit any BlacklistTags.
/// </summary>
[DataField("whitelistTags", customTypeSerializer: typeof(PrototypeIdListSerializer<TagPrototype>))]
public List<string>? WhitelistTags = null;

/// <summary>
/// Food containing any of these tags is not affected.
/// </summary>
[DataField("blacklistTags", customTypeSerializer: typeof(PrototypeIdListSerializer<TagPrototype>))]
public List<string>? BlacklistTags = null;

/// <summary>
/// Factor that the reagent quantities are multiplied by.
/// </summary>
[DataField("factor")]
public FixedPoint2 Factor = 1f;

/// <summary>
/// Reagent that is used to replace the volume taken away by the Factor multiplication.
/// </summary>
[DataField("replacementReagent")]
public string? ReplacementReagentID = null;

public bool AffectsFood(EntityUid foodEnt, IEntityManager entityManager)
{
if (WhitelistTags is null)
return false;

var tagSys = entityManager.System<TagSystem>();

if (BlacklistTags is not null && tagSys.HasAnyTag(foodEnt, BlacklistTags))
return false;

return tagSys.HasAnyTag(foodEnt, WhitelistTags);
}

public Solution ModifySolution(Solution solution)
{
// In case someone forgot to set the reagents being replaced, we do nothing.
if (ReducedReagents is null || Factor <= 0f)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Проверьте значения Factor и ограничьте их до 1 для предотвращения отрицательных количеств.

Если Factor больше 1, вычисление removedQuantity может привести к отрицательным значениям, что приведёт к добавлению реагентов с отрицательным количеством на строке 86. Это может вызвать некорректное поведение. Рекомендуется добавить проверку, чтобы Factor был не больше 1.

Примените следующий дифф для исправления:

- if (ReducedReagents is null || Factor <= 0f)
+ if (ReducedReagents is null || Factor <= 0f || Factor > 1f)
    return solution;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (ReducedReagents is null || Factor <= 0f)
if (ReducedReagents is null || Factor <= 0f || Factor > 1f)

return solution;

// Recreating the list since we can't set quentities in-place.
List<ReagentQuantity> newReagents = new();
FixedPoint2 removedQuantity = 0f;
foreach (var quantity in solution.Contents)
{
if (!ReducedReagents.Contains(quantity.Reagent.Prototype))
{
newReagents.Add(quantity);
continue;
}

removedQuantity += quantity.Quantity;
newReagents.Add(new ReagentQuantity(quantity.Reagent, quantity.Quantity * Factor));
}
removedQuantity *= 1f - Factor;

if (ReplacementReagentID is string reagentId)
newReagents.Add(new ReagentQuantity(new ReagentId(reagentId, null), removedQuantity));
Comment on lines +85 to +86
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Добавьте проверку на нулевое значение removedQuantity перед добавлением заменяющего реагента.

Если removedQuantity равно нулю, добавление реагента с нулевым количеством может быть излишним. Рекомендуется добавить проверку, чтобы добавлять реагент только если removedQuantity больше нуля.

Примените следующий дифф для исправления:

- if (ReplacementReagentID is string reagentId)
+ if (removedQuantity > 0f && ReplacementReagentID is string reagentId)
    newReagents.Add(new ReagentQuantity(new ReagentId(reagentId, null), removedQuantity));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (ReplacementReagentID is string reagentId)
newReagents.Add(new ReagentQuantity(new ReagentId(reagentId, null), removedQuantity));
if (removedQuantity > 0f && ReplacementReagentID is string reagentId)
newReagents.Add(new ReagentQuantity(new ReagentId(reagentId, null), removedQuantity));


solution.SetContents(newReagents);
return solution;
}
}
}
2 changes: 2 additions & 0 deletions Resources/Locale/en-US/_LostParadise/Guidebook/effects.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
reagent-effect-guidebook-accumulate-reagent-reagent =
Accumulates as long as there's a {$reagent} source present in the bloodstream
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
reagent-name-indigestible-fibre = indigestible dietary fibre
reagent-desc-indigestible-fibre = Residues of a digestive system poorly adapted to plant-derived food.
2 changes: 2 additions & 0 deletions Resources/Locale/ru-RU/_LostParadise/Guidebook/effects.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
reagent-effect-guidebook-accumulate-reagent-reagent =
Накапливается в кровеносной системе, пока в ней имеется вещество, добавляющее {$reagent}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
reagent-name-indigestible-fibre = неперевариваемые растительные волокна
reagent-desc-indigestible-fibre = Остаточные продукты пищеварительной системы, плохо приспособленной к растительной пище.
20 changes: 20 additions & 0 deletions Resources/Prototypes/DeltaV/Body/Organs/vulpkanin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@
noSpawn: true
components:
- type: Stomach
poorlyDigestibleFood:
reducedReagents:
- Nutriment
- Vitamin
whitelistTags:
- Fruit # LostParadise's lore states the vulpkanin race isn't really adapted to plant food
- Vegetable
- Bread
- Pizza # Basic pizza is also bakery
- Wheat
blacklistTags:
- Meat # Meat-based food is excluded in order not to force the carnivores to be meat-purists
factor: 0.25
replacementReagent: LPPIndigestibleFiber
Evgencheg marked this conversation as resolved.
Show resolved Hide resolved
- type: SolutionContainerManager
solutions:
stomach:
Expand All @@ -13,3 +27,9 @@
reagents:
- ReagentId: UncookedAnimalProteins
Quantity: 5
- type: Metabolizer
maxReagents: 3
metabolizerTypes: [ Animal ]
groups:
- id: Food
- id: Drink
Evgencheg marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -2383,3 +2383,6 @@
effects:
- !type:SatiateThirst
factor: 4
- !type:AdjustReagent
reagent: Theobromine
amount: 0.04
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,9 @@
Quantity: 8
- ReagentId: Protein
Quantity: 2
- type: Tag
tags:
- Meat
Comment on lines +459 to +461
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Исправьте отступ для тега "Meat"

Изменение соответствует целям PR по обновлению тегов пищи. Однако есть небольшая проблема с отступом.

Пожалуйста, исправьте отступ для тега "Meat". Он должен быть на том же уровне, что и "tags:". Примените следующее изменение:

  - type: Tag
    tags:
-    - Meat
+      - Meat

После этого изменение можно считать утвержденным.

Committable suggestion was skipped due to low confidence.

🧰 Tools
🪛 yamllint

[error] 461-461: wrong indentation: expected 6 but found 4

(indentation)


- type: entity
name: chèvre chaud
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@
- state: margherita
- type: SliceableFood
slice: FoodPizzaMargheritaSlice
- type: Tag
tags:
- Pizza
- Vegetable
Comment on lines +81 to +84
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Исправьте отступы и удалите избыточный тег

Обратите внимание на следующие моменты:

  1. Отступы для тегов должны быть 6 пробелов вместо 4.
  2. Тег "Pizza" уже присутствует в родительском объекте и является избыточным.

Примените следующие изменения:

  - type: Tag
    tags:
-    - Pizza
-    - Vegetable
+      - Vegetable

Committable suggestion was skipped due to low confidence.

🧰 Tools
🪛 yamllint

[error] 83-83: wrong indentation: expected 6 but found 4

(indentation)


- type: entity
name: slice of margherita pizza
Expand All @@ -93,6 +97,10 @@
- type: Sprite
layers:
- state: margherita-slice
- type: Tag
tags:
- Pizza
- Vegetable

- type: entity
name: meat pizza
Expand Down Expand Up @@ -200,7 +208,11 @@
Quantity: 5
- ReagentId: Vitamin
Quantity: 5

- type: Tag
tags:
- Pizza
- Vegetable

- type: entity
name: slice of vegetable pizza
parent: FoodPizzaSliceBase
Expand Down Expand Up @@ -230,6 +242,10 @@
Quantity: 1
- ReagentId: Vitamin
Quantity: 1
- type: Tag
tags:
- Pizza
- Vegetable

# Tastes like crust, tomato, cheese, carrot.

Expand Down Expand Up @@ -321,6 +337,10 @@
Quantity: 5
- ReagentId: DoctorsDelight
Quantity: 6
- type: Tag
tags:
- Pizza
- Vegetable
Comment on lines +340 to +343
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Исправьте отступы и удалите избыточный тег

Необходимо внести следующие изменения:

  1. Исправьте отступы для тегов на 6 пробелов вместо 4.
  2. Удалите избыточный тег "Pizza", так как он уже присутствует в родительском объекте.

Примените следующие изменения:

  - type: Tag
    tags:
-    - Pizza
-    - Vegetable
+      - Vegetable
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- type: Tag
tags:
- Pizza
- Vegetable
- type: Tag
tags:
- Vegetable
🧰 Tools
🪛 yamllint

[error] 342-342: wrong indentation: expected 6 but found 4

(indentation)


- type: entity
name: slice of dank pizza
Expand Down Expand Up @@ -348,6 +368,10 @@
Quantity: 0.8
- ReagentId: DoctorsDelight
Quantity: 1
- type: Tag
tags:
- Pizza
- Vegetable
# Tastes like crust, tomato, cheese, meat, satisfaction.

- type: entity
Expand Down Expand Up @@ -411,6 +435,10 @@
- state: pineapple
- type: SliceableFood
slice: FoodPizzaPineappleSlice
- type: Tag
tags:
- Meat
- Pizza

- type: entity
name: slice of pineapple pizza
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- type: Tag
tags:
- Pizza
- Vegetable # Yes, I am aware that corn is technically a fruit, but the tagging system is enough of a mess as it is
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Одобрено с небольшим предложением по форматированию

Добавление тега "Vegetable" соответствует целям PR по обновлению механики питания. Комментарий предоставляет полезный контекст для решения о тегировании.

Небольшое предложение по улучшению:

Рекомендуется добавить пробел после символа # в комментарии для улучшения читаемости:

-    - Vegetable # Yes, I am aware that corn is technically a fruit, but the tagging system is enough of a mess as it is
+    - Vegetable # Yes, I am aware that corn is technically a fruit, but the tagging system is enough of a mess as it is

Committable suggestion was skipped due to low confidence.

🧰 Tools
🪛 yamllint

[warning] 27-27: too few spaces before comment

(comments)


- type: entity
name: slice of corncob crust pizza
Expand All @@ -49,6 +50,7 @@
- type: Tag
tags:
- Pizza
- Vegetable

- type: entity
name: firecracker pizza
Expand Down
Loading
Loading