feat: add combat and deleveling AI

This commit is contained in:
Иванов Иван
2024-08-15 17:23:24 +02:00
parent bdd026519f
commit 2943f7a50b
79 changed files with 61368 additions and 6746 deletions

View File

@@ -0,0 +1,19 @@
using Client.Domain.AI;
using Client.Domain.AI.IO;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client.Infrastructure.AI.IO
{
public class JsonConfigDeserializer : ConfigDeserializerInterface
{
public Config? Deserialize(string data)
{
return JsonConvert.DeserializeObject<Config>(data);
}
}
}

View File

@@ -0,0 +1,20 @@
using Client.Domain.AI;
using Client.Domain.AI.IO;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client.Infrastructure.AI.IO
{
public class JsonConfigSerializer : ConfigSerializerInterface
{
public string Serialize(Config config)
{
return JsonConvert.SerializeObject(config, Formatting.Indented, new JsonSerializerSettings() { Culture = CultureInfo.InvariantCulture, ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
}
}
}

View File

@@ -26,6 +26,8 @@ namespace Client.Infrastructure.Factories
{
case ItemTypeEnum.Etc:
return JsonConvert.DeserializeObject<EtcItem>(data, settings);
case ItemTypeEnum.Weapon:
return JsonConvert.DeserializeObject<WeaponItem>(data, settings);
default:
return JsonConvert.DeserializeObject<EtcItem>(data, settings); //fixme temporary
}

View File

@@ -0,0 +1,54 @@
using Client.Domain.Helpers;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Client.Infrastructure.Helpers
{
public class ConfigurationItemInfoHelper : ItemInfoHelperInterface
{
public List<ItemInfo> GetAllItems()
{
LoadItems();
return itemsInfo;
}
public ConfigurationItemInfoHelper(IConfiguration configuration)
{
this.configuration = configuration;
}
private void LoadItems()
{
if (itemsInfo.Count == 0)
{
var items = configuration.GetRequiredSection("itemInfo").GetChildren();
foreach (var item in items)
{
var id = uint.Parse(item.Key);
var isShot = false;
if (item != null)
{
bool.TryParse(item.GetSection("isShot").Value, out isShot);
}
itemsInfo.Add(new ItemInfo
{
Id = id,
Name = string.Format("{0} [{1}]", item?.GetRequiredSection("name").Value ?? "", id),
IsShot = isShot
});
}
}
}
private readonly IConfiguration configuration;
private List<ItemInfo> itemsInfo = new List<ItemInfo>();
}
}

View File

@@ -6,7 +6,6 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using static Client.Infrastructure.Helpers.ConfigurationExperienceHelper;
namespace Client.Infrastructure.Helpers
{
@@ -14,12 +13,30 @@ namespace Client.Infrastructure.Helpers
{
public uint GetLevel(uint id)
{
return GetNpcInfo(id).level;
LoadNpc();
if (npcInfo.ContainsKey(id))
{
return npcInfo[id].Level;
}
return 0;
}
public uint GetAggroRadius(uint id)
{
return GetNpcInfo(id).aggroRadius;
LoadNpc();
if (npcInfo.ContainsKey(id))
{
return npcInfo[id].AggroRadius;
}
return 0;
}
public List<NpcInfo> GetAllNpc()
{
LoadNpc();
return npcInfo.Select(x => x.Value).ToList();
}
public ConfigurationNpcInfoHelper(IConfiguration configuration)
@@ -27,36 +44,37 @@ namespace Client.Infrastructure.Helpers
this.configuration = configuration;
}
private NpcInfo GetNpcInfo(uint id)
private void LoadNpc()
{
if (!npcInfo.ContainsKey(id))
if (npcInfo.Count == 0)
{
var item = configuration.GetRequiredSection("npcInfo").GetChildren()
.Where(x => x.Key == id.ToString())
.FirstOrDefault();
uint level = 0;
uint aggroRadius = 0;
if (item != null)
var items = configuration.GetRequiredSection("npcInfo").GetChildren();
foreach (var item in items)
{
uint.TryParse(item.GetRequiredSection("level").Value, out level);
uint.TryParse(item.GetRequiredSection("aggroRadius").Value, out aggroRadius);
var id = uint.Parse(item.Key);
uint level = 0;
uint aggroRadius = 0;
bool isGuard = false;
if (item != null)
{
uint.TryParse(item.GetRequiredSection("level").Value, out level);
uint.TryParse(item.GetRequiredSection("aggroRadius").Value, out aggroRadius);
bool.TryParse(item.GetRequiredSection("isGuard").Value, out isGuard);
}
npcInfo[id] = new NpcInfo
{
Id = id,
Level = level,
AggroRadius = aggroRadius,
Name = string.Format("{0} [{1}]", item?.GetRequiredSection("name").Value ?? "", id),
IsGuard = isGuard
};
}
npcInfo[id] = new NpcInfo
{
level = level,
aggroRadius = aggroRadius
};
}
return npcInfo[id];
}
private readonly IConfiguration configuration;
private Dictionary<uint, NpcInfo> npcInfo = new Dictionary<uint, NpcInfo>();
private class NpcInfo
{
public uint level { get; set; }
public uint aggroRadius { get; set; }
}
}
}

View File

@@ -0,0 +1,53 @@
using Client.Domain.Helpers;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Client.Infrastructure.Helpers
{
public class ConfigurationSkillInfoHelper : SkillInfoHelperInterface
{
public Dictionary<uint, SkillInfo> GetAllSkills()
{
LoadSkills();
return skillsInfo;
}
public ConfigurationSkillInfoHelper(IConfiguration configuration)
{
this.configuration = configuration;
}
private void LoadSkills()
{
if (skillsInfo.Count == 0)
{
var items = configuration.GetRequiredSection("skillInfo").GetChildren();
foreach (var item in items)
{
var id = uint.Parse(item.Key);
var isActive = false;
if (item != null)
{
bool.TryParse(item.GetRequiredSection("IsActive").Value, out isActive);
}
skillsInfo[id]=(new SkillInfo
{
Id = id,
Name = string.Format("{0} [{1}]", item?.GetRequiredSection("name").Value ?? "", id),
IsActive = isActive
});
}
}
}
private readonly IConfiguration configuration;
private Dictionary<uint, SkillInfo> skillsInfo = new Dictionary<uint, SkillInfo>();
}
}

View File

@@ -28,7 +28,19 @@ namespace Client.Infrastructure.Service
private CancellationTokenSource? cancellationTokenSource;
public ObservableCollection<PathSegment> Path { get; private set; } = new ObservableCollection<PathSegment>();
public bool IsBusy { get; private set; } = false;
public bool IsLocked { get; private set; } = false;
public void Unlock()
{
IsLocked = false;
if (cancellationTokenSource != null)
{
cancellationTokenSource.Cancel();
cancellationTokenSource.Dispose();
cancellationTokenSource = null;
Path.Clear();
}
}
public async Task MoveUntilReachedAsync(Vector3 location)
{
@@ -41,7 +53,7 @@ namespace Client.Infrastructure.Service
public async Task<bool> MoveAsync(Vector3 location)
{
IsBusy = true;
IsLocked = true;
if (cancellationTokenSource != null)
{
@@ -55,11 +67,9 @@ namespace Client.Infrastructure.Service
{
return await Task.Run(async () =>
{
cancellationToken.ThrowIfCancellationRequested();
Debug.WriteLine("Find path start");
Debug.WriteLine("Find path started");
FindPath(location);
Debug.WriteLine("Find path finish");
Debug.WriteLine("Find path finished");
foreach (var node in Path.ToList())
@@ -69,19 +79,21 @@ namespace Client.Infrastructure.Service
var reached = await WaitForNodeReaching(cancellationToken, node);
if (!reached)
{
IsBusy = false;
IsLocked = false;
return false;
}
Path.Remove(node);
}
IsBusy = false;
IsLocked = false;
return true;
}, cancellationToken);
}
catch (OperationCanceledException)
{
IsBusy = false;
Debug.WriteLine("Path cancelled");
IsLocked = false;
return true;
}
}
@@ -118,13 +130,8 @@ namespace Client.Infrastructure.Service
var hero = worldHandler.Hero;
var start = DateTime.Now;
while (hero != null && !hero.Transform.Position.ApproximatelyEquals(node.To, nodeDistanceTolerance))
while (!token.IsCancellationRequested && hero != null && !hero.Transform.Position.ApproximatelyEquals(node.To, nodeDistanceTolerance))
{
if (token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
}
if (hero.Transform.Velocity.Equals(Vector3.Zero))
{
var elapsedSeconds = (DateTime.Now - start).TotalSeconds;
@@ -138,7 +145,9 @@ namespace Client.Infrastructure.Service
return false;
}
}
await Task.Delay(25);
token.ThrowIfCancellationRequested();
await Task.Delay(25, token);
}
return true;

View File

@@ -44,9 +44,9 @@ namespace Client.Infrastructure.Transports
Debug.WriteLine("Connected to main pipe\n");
}
}
public async Task StartReceiveAsync()
public async Task ReceiveAsync()
{
while (IsConnected())
if (IsConnected())
{
byte[] buffer = new byte[16384 * 2];
int readBytes = await mainPipe!.ReadAsync(buffer, 0, buffer.Length);