diff --git a/src/app/Edelstein.Application.Server/ProgramHost.cs b/src/app/Edelstein.Application.Server/ProgramHost.cs index 704234c91..65c3c9fce 100644 --- a/src/app/Edelstein.Application.Server/ProgramHost.cs +++ b/src/app/Edelstein.Application.Server/ProgramHost.cs @@ -180,7 +180,7 @@ public async Task StartAsync(CancellationToken cancellationToken) b.RegisterType().As().SingleInstance(); b.RegisterType().As().SingleInstance(); b.RegisterType().As().SingleInstance(); - b.RegisterType().As().SingleInstance(); + b.RegisterType().As().SingleInstance(); b.RegisterType().As().SingleInstance(); b.RegisterType().As().SingleInstance(); b.RegisterType().As().SingleInstance(); diff --git a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/FieldMob.cs b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/FieldMob.cs index 022255dc3..52fdb3605 100644 --- a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/FieldMob.cs +++ b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/FieldMob.cs @@ -1,7 +1,9 @@ using System.Collections.Immutable; +using Edelstein.Common.Gameplay.Game.Objects.Drop; using Edelstein.Common.Gameplay.Game.Objects.Mob.Stats; using Edelstein.Common.Gameplay.Game.Objects.Mob.Stats.Modify; using Edelstein.Common.Gameplay.Handling; +using Edelstein.Common.Gameplay.Models.Inventories.Items; using Edelstein.Common.Utilities.Packets; using Edelstein.Protocol.Gameplay.Game.Objects; using Edelstein.Protocol.Gameplay.Game.Objects.Mob; @@ -10,6 +12,7 @@ using Edelstein.Protocol.Gameplay.Game.Objects.Mob.Templates; using Edelstein.Protocol.Gameplay.Game.Objects.User; using Edelstein.Protocol.Gameplay.Game.Spatial; +using Edelstein.Protocol.Gameplay.Models.Inventories.Templates; using Edelstein.Protocol.Utilities.Packets; using Edelstein.Protocol.Utilities.Spatial; using Edelstein.Protocol.Utilities.Tickers; @@ -87,10 +90,31 @@ public async Task Damage(int damage, IFieldUser? attacker = null) if (HP <= 0) { - await Field.Leave(this, () => GetLeaveFieldPacket(FieldMobLeaveType.Etc)); - - if (attacker != null) + if (attacker != null) + { + var rewardPool = attacker.StageUser.Context.Managers.MobRewardPool; + var rewards = await rewardPool.CalculateRewards(attacker, this); + + foreach (var reward in rewards) + { + if (reward.ItemID == null) continue; + var template = await attacker.StageUser.Context.Templates.Item.Retrieve(reward.ItemID.Value); + if (template == null) continue; + + var position = Position; + var drop = new FieldDropItem( + position, + template.ToItemSlot(ItemVariationOption.Normal), + sourceID: ObjectID ?? 0 + ); + + await Field.Enter(drop, () => drop.GetEnterFieldPacket(1, position)); + } + _ = attacker.StageUser.Context.Managers.Quest.UpdateMobKill(attacker, Template.ID); + } + + await Field.Leave(this, () => GetLeaveFieldPacket(FieldMobLeaveType.Etc)); } } finally diff --git a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobReward.cs b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobReward.cs index 35fffb848..dba977598 100644 --- a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobReward.cs +++ b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobReward.cs @@ -2,7 +2,9 @@ namespace Edelstein.Common.Gameplay.Game.Objects.Mob.Rewards; -public record MobReward : IMobReward +public record MobReward( + int ID +) : IMobReward { public int? ItemID { get; init; } diff --git a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewardManager.cs b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewardManager.cs deleted file mode 100644 index 80372b720..000000000 --- a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewardManager.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Immutable; -using Edelstein.Protocol.Gameplay.Game.Objects.Mob; -using Edelstein.Protocol.Gameplay.Game.Objects.Mob.Rewards; -using Edelstein.Protocol.Gameplay.Game.Objects.User; - -namespace Edelstein.Common.Gameplay.Game.Objects.Mob.Rewards; - -public class MobRewardManager : IMobRewardManager -{ - private readonly IDictionary _rewards; - private readonly ICollection _rewardsAll; - - public MobRewardManager() - { - _rewards = new Dictionary(); - _rewardsAll = new List(); - } - - public Task Insert(int mobID, IMobReward reward) - { - if (!_rewards.TryGetValue(mobID, out var rewards)) - { - rewards = new MobRewards(); - _rewards[mobID] = rewards; - } - - rewards.Items.Add(reward); - return Task.CompletedTask; - } - - public Task InsertAll(IMobReward reward) - { - _rewardsAll.Add(reward); - return Task.CompletedTask; - } - - public Task> RetrieveAll(int mobID) - => Task.FromResult>(_rewardsAll - .Concat(_rewards.TryGetValue(mobID, out var rewards) ? rewards.Items : ImmutableArray.Empty) - .ToImmutableArray()); - - public async Task> RetrieveAvailable(IFieldUser user, IFieldMob mob) - => (await RetrieveAll(mob.Template.ID)) - .Where(r => true) // TODO - .ToImmutableArray(); -} diff --git a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewardManagerInit.cs b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewardManagerInit.cs deleted file mode 100644 index 12f367715..000000000 --- a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewardManagerInit.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Edelstein.Common.Gameplay.Game.Objects.Mob.Templates; -using Edelstein.Protocol.Gameplay.Contracts; -using Edelstein.Protocol.Gameplay.Game.Objects.Mob.Rewards; -using Edelstein.Protocol.Utilities.Pipelines; -using Edelstein.Protocol.Utilities.Templates; - -namespace Edelstein.Common.Gameplay.Game.Objects.Mob.Rewards; - -public class MobRewardManagerInit : IPipelinePlug -{ - private readonly ITemplateManager _templates; - private readonly IMobRewardManager _manager; - - public MobRewardManagerInit(ITemplateManager templates, IMobRewardManager manager) - { - _templates = templates; - _manager = manager; - } - - public async Task Handle(IPipelineContext ctx, StageStart message) - { - foreach (var rewards in await _templates.RetrieveAll()) - foreach (var item in rewards.Items) - await _manager.Insert(rewards.ID, item); - } -} diff --git a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewardPoolManager.cs b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewardPoolManager.cs new file mode 100644 index 000000000..06dc9084f --- /dev/null +++ b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewardPoolManager.cs @@ -0,0 +1,28 @@ +using System.Collections.Immutable; +using Edelstein.Common.Utilities.Repositories; +using Edelstein.Protocol.Gameplay.Game.Objects.Mob; +using Edelstein.Protocol.Gameplay.Game.Objects.Mob.Rewards; +using Edelstein.Protocol.Gameplay.Game.Objects.User; +using Edelstein.Protocol.Gameplay.Game.Rewards; +using Edelstein.Protocol.Utilities.Repositories; + +namespace Edelstein.Common.Gameplay.Game.Objects.Mob.Rewards; + +public class MobRewardPoolManager : + Repository>, + IMobRewardPoolManager +{ + public IRepository Global { get; } = new Repository(); + + public async Task> CalculateRewards(IFieldUser user, IFieldMob mob) + { + var pool = await Retrieve(mob.Template.ID); + var items = new List(); + + if (pool != null) + items.AddRange(await pool.RetrieveAll()); + items.AddRange(await Global.RetrieveAll()); + + return items.ToImmutableArray(); + } +} diff --git a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewardPoolManagerInit.cs b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewardPoolManagerInit.cs new file mode 100644 index 000000000..a30f517fa --- /dev/null +++ b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewardPoolManagerInit.cs @@ -0,0 +1,34 @@ +using Edelstein.Common.Gameplay.Game.Objects.Mob.Templates; +using Edelstein.Common.Gameplay.Game.Rewards; +using Edelstein.Protocol.Gameplay.Contracts; +using Edelstein.Protocol.Gameplay.Game.Objects.Mob.Rewards; +using Edelstein.Protocol.Utilities.Pipelines; +using Edelstein.Protocol.Utilities.Templates; + +namespace Edelstein.Common.Gameplay.Game.Objects.Mob.Rewards; + +public class MobRewardPoolManagerInit : IPipelinePlug +{ + private readonly ITemplateManager _templates; + private readonly IMobRewardPoolManager _manager; + + public MobRewardPoolManagerInit( + ITemplateManager templates, + IMobRewardPoolManager manager + ) + { + _templates = templates; + _manager = manager; + } + + public async Task Handle(IPipelineContext ctx, StageStart message) + { + foreach (var rewards in await _templates.RetrieveAll()) + { + var pool = new RewardPool(rewards.ID); + foreach (var item in rewards.Items) + await pool.Insert(item); + await _manager.Insert(pool); + } + } +} diff --git a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewards.cs b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewards.cs deleted file mode 100644 index b50656f68..000000000 --- a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Rewards/MobRewards.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Edelstein.Protocol.Gameplay.Game.Objects.Mob.Rewards; - -namespace Edelstein.Common.Gameplay.Game.Objects.Mob.Rewards; - -public class MobRewards -{ - public ICollection Items { get; } - - public MobRewards() - => Items = new List(); -} diff --git a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardsTemplate.cs b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardPoolTemplate.cs similarity index 62% rename from src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardsTemplate.cs rename to src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardPoolTemplate.cs index c775e9da0..7bb6cd6ef 100644 --- a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardsTemplate.cs +++ b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardPoolTemplate.cs @@ -6,16 +6,16 @@ namespace Edelstein.Common.Gameplay.Game.Objects.Mob.Templates; -public class MobRewardsTemplate : ITemplate +public class MobRewardPoolTemplate : ITemplate { public int ID { get; } - public ICollection Items { get; } + public ICollection Items { get; } - public MobRewardsTemplate(int id, IDataNode property) + public MobRewardPoolTemplate(int id, IDataNode property) { ID = id; Items = property.Children - .Select(p => new MobRewardsTemplateItem(Convert.ToInt32(p.Name), p.Cache())) + .Select(p => new MobRewardTemplate(Convert.ToInt32(p.Name), p.Cache())) .ToImmutableArray(); } } diff --git a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardsTemplateLoader.cs b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardPoolTemplateLoader.cs similarity index 70% rename from src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardsTemplateLoader.cs rename to src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardPoolTemplateLoader.cs index 2d2ef0272..83c165719 100644 --- a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardsTemplateLoader.cs +++ b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardPoolTemplateLoader.cs @@ -5,12 +5,12 @@ namespace Edelstein.Common.Gameplay.Game.Objects.Mob.Templates; -public class MobRewardsTemplateLoader : ITemplateLoader +public class MobRewardPoolTemplateLoader : ITemplateLoader { private readonly IDataNamespace _data; - private readonly ITemplateManager _manager; + private readonly ITemplateManager _manager; - public MobRewardsTemplateLoader(IDataNamespace data, ITemplateManager manager) + public MobRewardPoolTemplateLoader(IDataNamespace data, ITemplateManager manager) { _data = data; _manager = manager; @@ -22,9 +22,9 @@ await Task.WhenAll(_data.ResolvePath("Server/Reward.img")?.Children .Select(async n => { var id = Convert.ToInt32(n.Name); - await _manager.Insert(new TemplateProviderEager( + await _manager.Insert(new TemplateProviderEager( id, - new MobRewardsTemplate(id, n.Cache()) + new MobRewardPoolTemplate(id, n.Cache()) )); }) ?? Array.Empty()); diff --git a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardsTemplateItem.cs b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardTemplate.cs similarity index 88% rename from src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardsTemplateItem.cs rename to src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardTemplate.cs index e09353415..a76a1aeaf 100644 --- a/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardsTemplateItem.cs +++ b/src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/Templates/MobRewardTemplate.cs @@ -4,7 +4,7 @@ namespace Edelstein.Common.Gameplay.Game.Objects.Mob.Templates; -public class MobRewardsTemplateItem : ITemplate, IMobReward +public class MobRewardTemplate : ITemplate, IMobReward { public int ID { get; } @@ -26,7 +26,7 @@ public class MobRewardsTemplateItem : ITemplate, IMobReward public DateTime? DateStart { get; } public DateTime? DateEnd { get; } - public MobRewardsTemplateItem(int id, IDataNode property) + public MobRewardTemplate(int id, IDataNode property) { ID = id; diff --git a/src/common/Edelstein.Common.Gameplay.Game/Rewards/RewardPool.cs b/src/common/Edelstein.Common.Gameplay.Game/Rewards/RewardPool.cs new file mode 100644 index 000000000..f0e8a8689 --- /dev/null +++ b/src/common/Edelstein.Common.Gameplay.Game/Rewards/RewardPool.cs @@ -0,0 +1,14 @@ +using Edelstein.Common.Utilities.Repositories; +using Edelstein.Protocol.Gameplay.Game.Rewards; + +namespace Edelstein.Common.Gameplay.Game.Rewards; + +public class RewardPool : + Repository, + IRewardPool + where TReward : IReward +{ + public int ID { get; } + + public RewardPool(int id) => ID = id; +} diff --git a/src/common/Edelstein.Common.Gameplay.Game/Rewards/RewardPoolManager.cs b/src/common/Edelstein.Common.Gameplay.Game/Rewards/RewardPoolManager.cs new file mode 100644 index 000000000..4a28a660f --- /dev/null +++ b/src/common/Edelstein.Common.Gameplay.Game/Rewards/RewardPoolManager.cs @@ -0,0 +1,11 @@ +using Edelstein.Common.Utilities.Repositories; +using Edelstein.Protocol.Gameplay.Game.Rewards; + +namespace Edelstein.Common.Gameplay.Game.Rewards; + +public class RewardPoolManager : + Repository>, + IRewardPoolManager + where TReward : IReward +{ +} diff --git a/src/plugin/Edelstein.Plugin.Rue/Edelstein.Plugin.Rue.csproj b/src/plugin/Edelstein.Plugin.Rue/Edelstein.Plugin.Rue.csproj index 6fb03fa53..f514fa6dd 100644 --- a/src/plugin/Edelstein.Plugin.Rue/Edelstein.Plugin.Rue.csproj +++ b/src/plugin/Edelstein.Plugin.Rue/Edelstein.Plugin.Rue.csproj @@ -15,4 +15,8 @@ + + + + diff --git a/src/protocol/Edelstein.Protocol.Gameplay.Game/Contexts/GameContextManagers.cs b/src/protocol/Edelstein.Protocol.Gameplay.Game/Contexts/GameContextManagers.cs index 5cd1a31cf..16c6b311f 100644 --- a/src/protocol/Edelstein.Protocol.Gameplay.Game/Contexts/GameContextManagers.cs +++ b/src/protocol/Edelstein.Protocol.Gameplay.Game/Contexts/GameContextManagers.cs @@ -19,7 +19,7 @@ public record GameContextManagers( IContiMoveManager ContiMove, INamedConversationManager Conversation, INPCShopManager NPCShop, - IMobRewardManager MobReward, + IMobRewardPoolManager MobRewardPool, ISkillManager Skill, IQuestManager Quest, IModifiedQuestTimeManager QuestTime diff --git a/src/protocol/Edelstein.Protocol.Gameplay.Game/Objects/Mob/Rewards/IMobReward.cs b/src/protocol/Edelstein.Protocol.Gameplay.Game/Objects/Mob/Rewards/IMobReward.cs index e1121c9db..0b726c8db 100644 --- a/src/protocol/Edelstein.Protocol.Gameplay.Game/Objects/Mob/Rewards/IMobReward.cs +++ b/src/protocol/Edelstein.Protocol.Gameplay.Game/Objects/Mob/Rewards/IMobReward.cs @@ -1,6 +1,8 @@ -namespace Edelstein.Protocol.Gameplay.Game.Objects.Mob.Rewards; +using Edelstein.Protocol.Gameplay.Game.Rewards; -public interface IMobReward +namespace Edelstein.Protocol.Gameplay.Game.Objects.Mob.Rewards; + +public interface IMobReward : IReward { int? ItemID { get; } diff --git a/src/protocol/Edelstein.Protocol.Gameplay.Game/Objects/Mob/Rewards/IMobRewardManager.cs b/src/protocol/Edelstein.Protocol.Gameplay.Game/Objects/Mob/Rewards/IMobRewardManager.cs deleted file mode 100644 index f7e1ae104..000000000 --- a/src/protocol/Edelstein.Protocol.Gameplay.Game/Objects/Mob/Rewards/IMobRewardManager.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Edelstein.Protocol.Gameplay.Game.Objects.User; - -namespace Edelstein.Protocol.Gameplay.Game.Objects.Mob.Rewards; - -public interface IMobRewardManager -{ - Task Insert(int mobID, IMobReward reward); - Task InsertAll(IMobReward reward); - Task> RetrieveAll(int mobID); - Task> RetrieveAvailable(IFieldUser user, IFieldMob mob); -} diff --git a/src/protocol/Edelstein.Protocol.Gameplay.Game/Objects/Mob/Rewards/IMobRewardPoolManager.cs b/src/protocol/Edelstein.Protocol.Gameplay.Game/Objects/Mob/Rewards/IMobRewardPoolManager.cs new file mode 100644 index 000000000..adef7235b --- /dev/null +++ b/src/protocol/Edelstein.Protocol.Gameplay.Game/Objects/Mob/Rewards/IMobRewardPoolManager.cs @@ -0,0 +1,12 @@ +using Edelstein.Protocol.Gameplay.Game.Objects.User; +using Edelstein.Protocol.Gameplay.Game.Rewards; +using Edelstein.Protocol.Utilities.Repositories; + +namespace Edelstein.Protocol.Gameplay.Game.Objects.Mob.Rewards; + +public interface IMobRewardPoolManager : IRewardPoolManager +{ + IRepository Global { get; } + + Task> CalculateRewards(IFieldUser user, IFieldMob mob); +} diff --git a/src/protocol/Edelstein.Protocol.Gameplay.Game/Rewards/IReward.cs b/src/protocol/Edelstein.Protocol.Gameplay.Game/Rewards/IReward.cs new file mode 100644 index 000000000..75f7f42bc --- /dev/null +++ b/src/protocol/Edelstein.Protocol.Gameplay.Game/Rewards/IReward.cs @@ -0,0 +1,7 @@ +using Edelstein.Protocol.Utilities.Repositories; + +namespace Edelstein.Protocol.Gameplay.Game.Rewards; + +public interface IReward : IIdentifiable +{ +} diff --git a/src/protocol/Edelstein.Protocol.Gameplay.Game/Rewards/IRewardPool.cs b/src/protocol/Edelstein.Protocol.Gameplay.Game/Rewards/IRewardPool.cs new file mode 100644 index 000000000..8cfdbc44d --- /dev/null +++ b/src/protocol/Edelstein.Protocol.Gameplay.Game/Rewards/IRewardPool.cs @@ -0,0 +1,10 @@ +using Edelstein.Protocol.Utilities.Repositories; + +namespace Edelstein.Protocol.Gameplay.Game.Rewards; + +public interface IRewardPool : + IIdentifiable, + IRepository + where TReward : IReward +{ +} diff --git a/src/protocol/Edelstein.Protocol.Gameplay.Game/Rewards/IRewardPoolManager.cs b/src/protocol/Edelstein.Protocol.Gameplay.Game/Rewards/IRewardPoolManager.cs new file mode 100644 index 000000000..0674a5fd9 --- /dev/null +++ b/src/protocol/Edelstein.Protocol.Gameplay.Game/Rewards/IRewardPoolManager.cs @@ -0,0 +1,9 @@ +using Edelstein.Protocol.Utilities.Repositories; + +namespace Edelstein.Protocol.Gameplay.Game.Rewards; + +public interface IRewardPoolManager : + IRepository> + where TReward : IReward +{ +}