Полагаю, я столкнулся с проблемой дизайна ... которую я не знаю, как решить сам.Извините, но я должен предоставить некоторую базовую информацию о дизайне ...
Игра.Игроки, монстры, объекты, разные вещи могут находиться под разными эффектами:
public interface IEffect {}
Могут быть разные конкретные эффекты:
public interface IResistanceBuff : IEffect
{
void modifyIncomingDamage(Damage damage);
}
public interface IDamageBuff : IEffect
{
void modifyOutgoingDamage(Damage damage);
}
Почему так?Ну, концепция это, чтобы избежать дублирования кода.Например, таким образом я могу унифицировать уменьшение урона от сопротивлений типа и, например, ношение брони.Я просто делаю класс Type
, а класс Armor
реализует IResistanceBuff
.(Точно так же класс Weapon
будет реализовывать IDamageBuff
).
Но некоторые эффекты являются временными, а не постоянными.Для этого у нас будет:
public interface ITemporaryEffect : IEffect
{
long TimeRemaining {get; set;}
}
Опять же, цель здесь состоит в том, чтобы избежать дублирования кода.Например, класс PotionOfMight
будет реализовывать интерфейс IDamageBuff
и наследуется от абстрактного класса Potion
, который, в свою очередь, будет реализовывать интерфейс ITemporaryEffect
.Или у нас будет IStun
интерфейс, который будет реализовывать ITemporaryEffect
.
Теперь каждый объект, который может находиться под определенными эффектами, будет хранить коллекцию (HashSet
может быть?) Всех эффектов, под которыми он находится.Это для того, чтобы можно было легче назвать эти эффекты.Например, у персонажа будет свойство public HashSet<IResistanceBuff> ResistanceBuffs {get; private set;}
, поэтому мы можем сделать метод TakeDamage
персонажа похожим на это:
void TakeDamage(Damage damage)
{
this.ResistanceBuffs.ForEach(resistanceBuff =>
resistanceBuff.modifyIncomingDamage(damage)
);
this.HP -= damage.Amount;
if(this.HP <= 0) {
this.Faint();
}
}
Но здесь возникает проблема.Я хочу иметь один фрагмент кода для обновления оставшейся длительности временных эффектов и удаления тех, чья длительность истекла.
Моя ( не работает, по замыслу C # ) идея для этого быласоздать класс Character
(и любой другой класс, представляющий объект, который может находиться под любым видом Effect
- это означает даже WorldMap
, потому что я думал, что буду сохранять погодные условия, как Effects
, примененный кworld) внедрить IEffectStorage
интерфейс:
public interface IEffectStorage
{
List<HashSet<IEffect>> AllEffects {get;}
}
public class Character : IEffectStorage
{
// ...
public HashSet<IResistanceBuff> ResistanceBuffs {get; private set;}
public HashSet<IDamageBuff> DamageBuffs {get; private set;}
// ...
public List<HashSet<IEffect>> AllEffects =>
new List<HashSet<IEffect>> {ResistanceBuffs, DamageBuffs, /* ... */};
}
Теперь работа с истечением временного эффекта была бы обязанностью статического класса Effect
:
public static class Effect
{
public static void ExpireTemporaryEffects(IEffectStorage effectStorage)
{
effectStorage.AllEffects.ForEach(effectSet =>
{
var effects = effectSet.ToList();
effects.ForEach(effect =>
{
if(effect is ITemporaryEffect) {
effect.TimeRemaining--;
if(effect.TimeRemaining <= 0) {
effectSet.Remove(effect);
}
}
});
});
}
}
Но, конечно, какЯ сказал, что не могу этого сделать.
Теперь я могу начать искать какие-то хакерские и / или уродливые способы заставить этот дизайн работать.И наоборот, я могу рассуждать, что, скорее всего, я пытаюсь что-то предпринять против разработки языка программирования C # и / или парадигмы ООП из-за того, что я недостаточно хорошо понимаю эту парадигму ... Тем более, что это первый проект этогоРазмер я делаю самостоятельно, я решаю сделать последний ... Так что я задаю этот вопрос :) Мой дизайн все не так, и если да, то как это исправить?
Извините задлина этого поста, но я чувствую, что вся информация выше необходима.