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

Implement mob reward loading, managers, and drops while kill monster #88

Merged
merged 3 commits into from
Dec 7, 2023
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
3 changes: 3 additions & 0 deletions src/app/Edelstein.Application.Server/ProgramHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Edelstein.Common.Gameplay.Game.Combat;
using Edelstein.Common.Gameplay.Game.Continents;
using Edelstein.Common.Gameplay.Game.Conversations;
using Edelstein.Common.Gameplay.Game.Objects.Mob.Rewards;
using Edelstein.Common.Gameplay.Game.Objects.NPC;
using Edelstein.Common.Gameplay.Game.Quests;
using Edelstein.Common.Gameplay.Handling;
Expand All @@ -29,6 +30,7 @@
using Edelstein.Protocol.Gameplay.Game.Contexts;
using Edelstein.Protocol.Gameplay.Game.Continents;
using Edelstein.Protocol.Gameplay.Game.Conversations;
using Edelstein.Protocol.Gameplay.Game.Objects.Mob.Rewards;
using Edelstein.Protocol.Gameplay.Game.Objects.NPC;
using Edelstein.Protocol.Gameplay.Game.Quests;
using Edelstein.Protocol.Gameplay.Login;
Expand Down Expand Up @@ -178,6 +180,7 @@ public async Task StartAsync(CancellationToken cancellationToken)
b.RegisterType<ContiMoveManager>().As<IContiMoveManager>().SingleInstance();
b.RegisterType<ScriptedConversationManager>().As<INamedConversationManager>().SingleInstance();
b.RegisterType<NPCShopManager>().As<INPCShopManager>().SingleInstance();
b.RegisterType<MobRewardPoolManager>().As<IMobRewardPoolManager>().SingleInstance();
b.RegisterType<SkillManager>().As<ISkillManager>().SingleInstance();
b.RegisterType<ModifiedQuestTimeManager>().As<IModifiedQuestTimeManager>().SingleInstance();
b.RegisterType<QuestManager>().As<IQuestManager>().SingleInstance();
Expand Down
30 changes: 27 additions & 3 deletions src/common/Edelstein.Common.Gameplay.Game/Objects/Mob/FieldMob.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Edelstein.Protocol.Gameplay.Game.Objects.Mob.Rewards;

namespace Edelstein.Common.Gameplay.Game.Objects.Mob.Rewards;

public record MobReward(
int ID
) : IMobReward
{
public int? ItemID { get; init; }

public int? Money { get; init; }

public int? NumberMin { get; init; }
public int? NumberMax { get; init; }

public int? ReqQuest { get; init; }

public int? ReqLevelMin { get; init; }
public int? ReqLevelMax { get; init; }

public int? ReqMobLevelMin { get; init; }
public int? ReqMobLevelMax { get; init; }

public DateTime? DateStart { get; init; }
public DateTime? DateEnd { get; init; }
}
Original file line number Diff line number Diff line change
@@ -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<int, IRewardPool<IMobReward>>,
IMobRewardPoolManager
{
public IRepository<int, IMobReward> Global { get; } = new Repository<int, IMobReward>();

public async Task<ICollection<IMobReward>> CalculateRewards(IFieldUser user, IFieldMob mob)
{
var pool = await Retrieve(mob.Template.ID);
var items = new List<IMobReward>();

if (pool != null)
items.AddRange(await pool.RetrieveAll());
items.AddRange(await Global.RetrieveAll());

return items.ToImmutableArray();
}
}
Original file line number Diff line number Diff line change
@@ -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<StageStart>
{
private readonly ITemplateManager<MobRewardPoolTemplate> _templates;
private readonly IMobRewardPoolManager _manager;

public MobRewardPoolManagerInit(
ITemplateManager<MobRewardPoolTemplate> 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<IMobReward>(rewards.ID);
foreach (var item in rewards.Items)
await pool.Insert(item);
await _manager.Insert(pool);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Collections.Immutable;
using Duey.Abstractions;
using Edelstein.Common.Gameplay.Game.Objects.NPC.Templates;
using Edelstein.Protocol.Gameplay.Game.Objects.NPC;
using Edelstein.Protocol.Utilities.Templates;

namespace Edelstein.Common.Gameplay.Game.Objects.Mob.Templates;

public class MobRewardPoolTemplate : ITemplate
{
public int ID { get; }
public ICollection<MobRewardTemplate> Items { get; }

public MobRewardPoolTemplate(int id, IDataNode property)
{
ID = id;
Items = property.Children
.Select(p => new MobRewardTemplate(Convert.ToInt32(p.Name), p.Cache()))
.ToImmutableArray();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Duey.Abstractions;
using Edelstein.Common.Gameplay.Game.Objects.NPC.Templates;
using Edelstein.Common.Utilities.Templates;
using Edelstein.Protocol.Utilities.Templates;

namespace Edelstein.Common.Gameplay.Game.Objects.Mob.Templates;

public class MobRewardPoolTemplateLoader : ITemplateLoader
{
private readonly IDataNamespace _data;
private readonly ITemplateManager<MobRewardPoolTemplate> _manager;

public MobRewardPoolTemplateLoader(IDataNamespace data, ITemplateManager<MobRewardPoolTemplate> manager)
{
_data = data;
_manager = manager;
}

public async Task<int> Load()
{
await Task.WhenAll(_data.ResolvePath("Server/Reward.img")?.Children
.Select(async n =>
{
var id = Convert.ToInt32(n.Name);
await _manager.Insert(new TemplateProviderEager<MobRewardPoolTemplate>(
id,
new MobRewardPoolTemplate(id, n.Cache())
));
}) ?? Array.Empty<Task>());

return _manager.Count;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Duey.Abstractions;
using Edelstein.Protocol.Gameplay.Game.Objects.Mob.Rewards;
using Edelstein.Protocol.Utilities.Templates;

namespace Edelstein.Common.Gameplay.Game.Objects.Mob.Templates;

public class MobRewardTemplate : ITemplate, IMobReward
{
public int ID { get; }

public int? ItemID { get; }

public int? Money { get; }

public int? NumberMin { get; }
public int? NumberMax { get; }

public int? ReqQuest { get; }

public int? ReqLevelMin { get; }
public int? ReqLevelMax { get; }

public int? ReqMobLevelMin { get; }
public int? ReqMobLevelMax { get; }

public DateTime? DateStart { get; }
public DateTime? DateEnd { get; }

public MobRewardTemplate(int id, IDataNode property)
{
ID = id;

ItemID = property.ResolveInt("item");

Money = property.ResolveInt("money");

NumberMin = property.ResolveInt("min");
NumberMax = property.ResolveInt("max");
}
}
14 changes: 14 additions & 0 deletions src/common/Edelstein.Common.Gameplay.Game/Rewards/RewardPool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Edelstein.Common.Utilities.Repositories;
using Edelstein.Protocol.Gameplay.Game.Rewards;

namespace Edelstein.Common.Gameplay.Game.Rewards;

public class RewardPool<TReward> :
Repository<int, TReward>,
IRewardPool<TReward>
where TReward : IReward
{
public int ID { get; }

public RewardPool(int id) => ID = id;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Edelstein.Common.Utilities.Repositories;
using Edelstein.Protocol.Gameplay.Game.Rewards;

namespace Edelstein.Common.Gameplay.Game.Rewards;

public class RewardPoolManager<TReward> :
Repository<int, IRewardPool<TReward>>,
IRewardPoolManager<TReward>
where TReward : IReward
{
}
4 changes: 4 additions & 0 deletions src/plugin/Edelstein.Plugin.Rue/Edelstein.Plugin.Rue.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@
<PackageReference Include="TrieNet" Version="1.0.3.26316" />
</ItemGroup>

<ItemGroup>
<Folder Include="Commands\v2\" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Edelstein.Protocol.Gameplay.Game.Combat;
using Edelstein.Protocol.Gameplay.Game.Continents;
using Edelstein.Protocol.Gameplay.Game.Conversations;
using Edelstein.Protocol.Gameplay.Game.Objects.Mob.Rewards;
using Edelstein.Protocol.Gameplay.Game.Objects.NPC;
using Edelstein.Protocol.Gameplay.Game.Quests;
using Edelstein.Protocol.Gameplay.Models.Inventories;
Expand All @@ -18,6 +19,7 @@ public record GameContextManagers(
IContiMoveManager ContiMove,
INamedConversationManager Conversation,
INPCShopManager NPCShop,
IMobRewardPoolManager MobRewardPool,
ISkillManager Skill,
IQuestManager Quest,
IModifiedQuestTimeManager QuestTime
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Edelstein.Protocol.Gameplay.Game.Rewards;

namespace Edelstein.Protocol.Gameplay.Game.Objects.Mob.Rewards;

public interface IMobReward : IReward
{
int? ItemID { get; }

int? Money { get; }

int? NumberMin { get; }
int? NumberMax { get; }

int? ReqQuest { get; }

int? ReqLevelMin { get; }
int? ReqLevelMax { get; }

int? ReqMobLevelMin { get; }
int? ReqMobLevelMax { get; }

DateTime? DateStart { get; }
DateTime? DateEnd { get; }
}
Original file line number Diff line number Diff line change
@@ -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<IMobReward>
{
IRepository<int, IMobReward> Global { get; }

Task<ICollection<IMobReward>> CalculateRewards(IFieldUser user, IFieldMob mob);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using Edelstein.Protocol.Utilities.Repositories;

namespace Edelstein.Protocol.Gameplay.Game.Rewards;

public interface IReward : IIdentifiable<int>
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Edelstein.Protocol.Utilities.Repositories;

namespace Edelstein.Protocol.Gameplay.Game.Rewards;

public interface IRewardPool<TReward> :
IIdentifiable<int>,
IRepository<int, TReward>
where TReward : IReward
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Edelstein.Protocol.Utilities.Repositories;

namespace Edelstein.Protocol.Gameplay.Game.Rewards;

public interface IRewardPoolManager<TReward> :
IRepository<int, IRewardPool<TReward>>
where TReward : IReward
{
}
Loading