diff --git a/src/Perpetuum.AdminTool/App.config b/src/Perpetuum.AdminTool/App.config
index 731f6de6c..ea62b9603 100644
--- a/src/Perpetuum.AdminTool/App.config
+++ b/src/Perpetuum.AdminTool/App.config
@@ -1,6 +1,30 @@
-
+
-
+
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Perpetuum.AdminTool/Perpetuum.AdminTool.csproj b/src/Perpetuum.AdminTool/Perpetuum.AdminTool.csproj
index 7ebcfe590..03a4c51c6 100644
--- a/src/Perpetuum.AdminTool/Perpetuum.AdminTool.csproj
+++ b/src/Perpetuum.AdminTool/Perpetuum.AdminTool.csproj
@@ -8,11 +8,12 @@
WinExe
Perpetuum.AdminTool
Perpetuum.AdminTool
- v4.6.1
+ v4.6.2
512
{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
4
true
+
x64
@@ -46,8 +47,8 @@
..\..\packages\Autofac.4.6.1\lib\net45\Autofac.dll
-
- ..\..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll
+
+ ..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll
diff --git a/src/Perpetuum.AdminTool/Properties/Resources.Designer.cs b/src/Perpetuum.AdminTool/Properties/Resources.Designer.cs
index 462013854..488c14e7b 100644
--- a/src/Perpetuum.AdminTool/Properties/Resources.Designer.cs
+++ b/src/Perpetuum.AdminTool/Properties/Resources.Designer.cs
@@ -8,10 +8,10 @@
//
//------------------------------------------------------------------------------
-namespace Perpetuum.AdminTool.Properties
-{
-
-
+namespace Perpetuum.AdminTool.Properties {
+ using System;
+
+
///
/// A strongly-typed resource class, for looking up localized strings, etc.
///
@@ -19,51 +19,43 @@ namespace Perpetuum.AdminTool.Properties
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class Resources
- {
-
+ internal class Resources {
+
private static global::System.Resources.ResourceManager resourceMan;
-
+
private static global::System.Globalization.CultureInfo resourceCulture;
-
+
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Resources()
- {
+ internal Resources() {
}
-
+
///
/// Returns the cached ResourceManager instance used by this class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager
- {
- get
- {
- if ((resourceMan == null))
- {
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Perpetuum.AdminTool.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
-
+
///
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture
- {
- get
- {
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
return resourceCulture;
}
- set
- {
+ set {
resourceCulture = value;
}
}
diff --git a/src/Perpetuum.AdminTool/Properties/Settings.Designer.cs b/src/Perpetuum.AdminTool/Properties/Settings.Designer.cs
index 65ecd68a2..0c6287134 100644
--- a/src/Perpetuum.AdminTool/Properties/Settings.Designer.cs
+++ b/src/Perpetuum.AdminTool/Properties/Settings.Designer.cs
@@ -8,21 +8,17 @@
//
//------------------------------------------------------------------------------
-namespace Perpetuum.AdminTool.Properties
-{
-
-
+namespace Perpetuum.AdminTool.Properties {
+
+
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
- internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
- {
-
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.13.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
-
- public static Settings Default
- {
- get
- {
+
+ public static Settings Default {
+ get {
return defaultInstance;
}
}
diff --git a/src/Perpetuum.AdminTool/packages.config b/src/Perpetuum.AdminTool/packages.config
index 4e5036580..bb31bf4e9 100644
--- a/src/Perpetuum.AdminTool/packages.config
+++ b/src/Perpetuum.AdminTool/packages.config
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/src/Perpetuum.Bootstrapper/Modules/NpcsModule.cs b/src/Perpetuum.Bootstrapper/Modules/NpcsModule.cs
index fb24c1f74..7a5c39543 100644
--- a/src/Perpetuum.Bootstrapper/Modules/NpcsModule.cs
+++ b/src/Perpetuum.Bootstrapper/Modules/NpcsModule.cs
@@ -13,6 +13,7 @@
using Perpetuum.Zones.NpcSystem.Presences.RandomExpiringPresence;
using Perpetuum.Zones.NpcSystem.Reinforcements;
using Perpetuum.Zones.NpcSystem.SafeSpawnPoints;
+using Perpetuum.Zones.NpcSystem.SapAttackers;
using System;
namespace Perpetuum.Bootstrapper.Modules
@@ -24,6 +25,7 @@ protected override void Load(ContainerBuilder builder)
_ = builder.RegisterType().As();
_ = builder.RegisterType().SingleInstance();
_ = builder.RegisterType().SingleInstance().As();
+ _ = builder.RegisterType().SingleInstance().As();
_ = builder.RegisterType().As();
_ = builder.RegisterType();
diff --git a/src/Perpetuum.Bootstrapper/Modules/TerrainsModule.cs b/src/Perpetuum.Bootstrapper/Modules/TerrainsModule.cs
index 0ef8e7bfd..cb49723c8 100644
--- a/src/Perpetuum.Bootstrapper/Modules/TerrainsModule.cs
+++ b/src/Perpetuum.Bootstrapper/Modules/TerrainsModule.cs
@@ -4,6 +4,7 @@
using Perpetuum.Threading.Process;
using Perpetuum.Zones;
using Perpetuum.Zones.NpcSystem.Reinforcements;
+using Perpetuum.Zones.NpcSystem.SapAttackers;
using Perpetuum.Zones.Scanning.Scanners;
using Perpetuum.Zones.Terrains;
using Perpetuum.Zones.Terrains.Materials;
@@ -26,9 +27,11 @@ protected override void Load(ContainerBuilder builder)
return zone =>
{
IMineralConfigurationReader reader = ctx.Resolve();
- OreNpcSpawner listener = new OreNpcSpawner(zone, ctx.Resolve(), reader);
+ OreNpcSpawner oreNpcSpawnlistener = new OreNpcSpawner(zone, ctx.Resolve(), ctx.Resolve(), reader);
+ SapAttackerSpawner sapAttackerSpawnlistener = new SapAttackerSpawner(zone, ctx.Resolve(), ctx.Resolve());
EventListenerService eventListenerService = ctx.Resolve();
- eventListenerService.AttachListener(listener);
+ eventListenerService.AttachListener(oreNpcSpawnlistener);
+ eventListenerService.AttachListener(sapAttackerSpawnlistener);
if (zone is TrainingZone)
{
GravelRepository repo = ctx.Resolve();
diff --git a/src/Perpetuum.Bootstrapper/Modules/ZonesModule.cs b/src/Perpetuum.Bootstrapper/Modules/ZonesModule.cs
index 2a4e5a2db..6abc97c11 100644
--- a/src/Perpetuum.Bootstrapper/Modules/ZonesModule.cs
+++ b/src/Perpetuum.Bootstrapper/Modules/ZonesModule.cs
@@ -22,6 +22,7 @@
using Perpetuum.Zones.NpcSystem.Presences;
using Perpetuum.Zones.NpcSystem.Reinforcements;
using Perpetuum.Zones.NpcSystem.SafeSpawnPoints;
+using Perpetuum.Zones.NpcSystem.SapAttackers;
using Perpetuum.Zones.PBS;
using Perpetuum.Zones.Scanning.Results;
using Perpetuum.Zones.Teleporting;
@@ -172,7 +173,7 @@ void RegisterZone(ZoneType type) where T : Zone
zone.PlayerStateManager = ctx.Resolve>().Invoke(zone);
}
- ctx.Resolve().AttachListener(new NpcReinforcementSpawner(zone, ctx.Resolve()));
+ ctx.Resolve().AttachListener(new NpcReinforcementSpawner(zone, ctx.Resolve(), ctx.Resolve()));
WeatherEventListener listener = ctx.Resolve>().Invoke(zone);
listener.Subscribe(zone.Weather);
diff --git a/src/Perpetuum.Bootstrapper/Perpetuum.Bootstrapper.csproj b/src/Perpetuum.Bootstrapper/Perpetuum.Bootstrapper.csproj
index 73e0e121d..df756e342 100644
--- a/src/Perpetuum.Bootstrapper/Perpetuum.Bootstrapper.csproj
+++ b/src/Perpetuum.Bootstrapper/Perpetuum.Bootstrapper.csproj
@@ -9,7 +9,7 @@
Properties
Perpetuum.Bootstrapper
Perpetuum.Bootstrapper
- v4.6.1
+ v4.6.2
512
@@ -36,23 +36,32 @@
..\..\packages\Autofac.4.6.1\lib\net45\Autofac.dll
-
- ..\..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll
+
+ ..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll
..\..\packages\Open.NAT.2.1.0.0\lib\net45\Open.Nat.dll
-
- ..\..\packages\System.Collections.Immutable.1.4.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
+ ..\..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+ ..\..\packages\System.Collections.Immutable.9.0.5\lib\netstandard2.0\System.Collections.Immutable.dll
+
+ ..\..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll
+
-
- ..\..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll
+
+ ..\..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+ ..\..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
@@ -99,6 +108,7 @@
+
diff --git a/src/Perpetuum.Bootstrapper/PerpetuumBootstrapper.cs b/src/Perpetuum.Bootstrapper/PerpetuumBootstrapper.cs
index 6ef3a85f7..eb714896a 100644
--- a/src/Perpetuum.Bootstrapper/PerpetuumBootstrapper.cs
+++ b/src/Perpetuum.Bootstrapper/PerpetuumBootstrapper.cs
@@ -440,7 +440,6 @@ private void InitContainer(string gameRoot)
_ = _builder.RegisterType();
_ = _builder.RegisterType().As();
-
_ = _builder.Register(x =>
{
GlobalConfiguration cfg = x.Resolve();
@@ -556,6 +555,9 @@ private void InitRelayManager()
_ = _builder.RegisterType();
_ = _builder.RegisterType().As>();
_ = _builder.RegisterType().As>();
+ _ = _builder.RegisterType().As>();
+ _ = _builder.RegisterType();
+
_ = _builder.RegisterType().SingleInstance().OnActivated(e =>
{
e.Context.Resolve().AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromSeconds(0.75)));
@@ -565,6 +567,7 @@ private void InitRelayManager()
e.Instance.AttachListener(e.Context.Resolve());
e.Instance.AttachListener(e.Context.Resolve());
e.Instance.AttachListener(e.Context.Resolve());
+ e.Instance.AttachListener(e.Context.Resolve());
GameTimeObserver obs = new GameTimeObserver(e.Instance);
obs.Subscribe(e.Context.Resolve());
});
diff --git a/src/Perpetuum.Bootstrapper/app.config b/src/Perpetuum.Bootstrapper/app.config
new file mode 100644
index 000000000..99e9a32a1
--- /dev/null
+++ b/src/Perpetuum.Bootstrapper/app.config
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Perpetuum.Bootstrapper/packages.config b/src/Perpetuum.Bootstrapper/packages.config
index f6af12342..cce78c9e4 100644
--- a/src/Perpetuum.Bootstrapper/packages.config
+++ b/src/Perpetuum.Bootstrapper/packages.config
@@ -1,8 +1,11 @@
-
+
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Perpetuum.ExportedTypes/Perpetuum.ExportedTypes.csproj b/src/Perpetuum.ExportedTypes/Perpetuum.ExportedTypes.csproj
index 89ba0019c..dc3da0705 100644
--- a/src/Perpetuum.ExportedTypes/Perpetuum.ExportedTypes.csproj
+++ b/src/Perpetuum.ExportedTypes/Perpetuum.ExportedTypes.csproj
@@ -9,7 +9,7 @@
Properties
Perpetuum.ExportedTypes
Perpetuum.ExportedTypes
- v4.6.1
+ v4.6.2
512
diff --git a/src/Perpetuum.RequestHandlers/Perpetuum.RequestHandlers.csproj b/src/Perpetuum.RequestHandlers/Perpetuum.RequestHandlers.csproj
index a0a729793..0613273b6 100644
--- a/src/Perpetuum.RequestHandlers/Perpetuum.RequestHandlers.csproj
+++ b/src/Perpetuum.RequestHandlers/Perpetuum.RequestHandlers.csproj
@@ -9,7 +9,7 @@
Properties
Perpetuum.RequestHandlers
Perpetuum.RequestHandlers
- v4.6.1
+ v4.6.2
512
@@ -34,13 +34,25 @@
-
- ..\..\packages\System.Collections.Immutable.1.4.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
+ ..\..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+ ..\..\packages\System.Collections.Immutable.9.0.5\lib\netstandard2.0\System.Collections.Immutable.dll
+
+ ..\..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll
+
+
+ ..\..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
@@ -644,6 +656,7 @@
+
diff --git a/src/Perpetuum.RequestHandlers/app.config b/src/Perpetuum.RequestHandlers/app.config
new file mode 100644
index 000000000..a2fe38b09
--- /dev/null
+++ b/src/Perpetuum.RequestHandlers/app.config
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Perpetuum.RequestHandlers/packages.config b/src/Perpetuum.RequestHandlers/packages.config
index d205d2758..e5b218db4 100644
--- a/src/Perpetuum.RequestHandlers/packages.config
+++ b/src/Perpetuum.RequestHandlers/packages.config
@@ -1,4 +1,8 @@
-
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Perpetuum.Server/Perpetuum.Server.csproj b/src/Perpetuum.Server/Perpetuum.Server.csproj
index b4b385ded..d054fcbf8 100644
--- a/src/Perpetuum.Server/Perpetuum.Server.csproj
+++ b/src/Perpetuum.Server/Perpetuum.Server.csproj
@@ -10,7 +10,7 @@
Properties
Perpetuum.Server
Perpetuum.Server
- v4.6.1
+ v4.6.2
512
diff --git a/src/Perpetuum.Server/app.config b/src/Perpetuum.Server/app.config
index 3dbff35f4..54f2f327e 100644
--- a/src/Perpetuum.Server/app.config
+++ b/src/Perpetuum.Server/app.config
@@ -1,3 +1,32 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Perpetuum.ServerService/App.config b/src/Perpetuum.ServerService/App.config
index 070227f63..2123b5bba 100644
--- a/src/Perpetuum.ServerService/App.config
+++ b/src/Perpetuum.ServerService/App.config
@@ -1,12 +1,12 @@
-
+
-
-
+
+
-
+
@@ -15,4 +15,32 @@
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Perpetuum.ServerService/Perpetuum.ServerService.csproj b/src/Perpetuum.ServerService/Perpetuum.ServerService.csproj
index a226ff8d8..60451e3fb 100644
--- a/src/Perpetuum.ServerService/Perpetuum.ServerService.csproj
+++ b/src/Perpetuum.ServerService/Perpetuum.ServerService.csproj
@@ -8,7 +8,7 @@
WinExe
Perpetuum.ServerService
Perpetuum.ServerService
- v4.6.1
+ v4.6.2
512
true
publish\
@@ -26,6 +26,7 @@
false
false
true
+
x64
diff --git a/src/Perpetuum.ServerService/Properties/Resources.Designer.cs b/src/Perpetuum.ServerService/Properties/Resources.Designer.cs
index 58f9c9d07..165b8249e 100644
--- a/src/Perpetuum.ServerService/Properties/Resources.Designer.cs
+++ b/src/Perpetuum.ServerService/Properties/Resources.Designer.cs
@@ -19,7 +19,7 @@ namespace Perpetuum.ServerService.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
diff --git a/src/Perpetuum.ServerService/Properties/Settings.Designer.cs b/src/Perpetuum.ServerService/Properties/Settings.Designer.cs
index 927ab6498..54b2474e9 100644
--- a/src/Perpetuum.ServerService/Properties/Settings.Designer.cs
+++ b/src/Perpetuum.ServerService/Properties/Settings.Designer.cs
@@ -12,7 +12,7 @@ namespace Perpetuum.ServerService.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.11.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.13.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
diff --git a/src/Perpetuum/GlobalConfiguration.cs b/src/Perpetuum/GlobalConfiguration.cs
index 0689cebcb..9fd5157a7 100644
--- a/src/Perpetuum/GlobalConfiguration.cs
+++ b/src/Perpetuum/GlobalConfiguration.cs
@@ -42,5 +42,13 @@ public class GlobalConfiguration
// Default camouflage bonus value.
[DefaultValue(5), JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public int CamouflageBonus { get; set; }
+
+ public string WebHookId { get; set; }
+
+ public string WebHookOAuth { get; set; }
+
+ public string DiscordBotToken { get; set; }
+
+ public string OpHelpChannelId { get; set; }
}
}
diff --git a/src/Perpetuum/Perpetuum.csproj b/src/Perpetuum/Perpetuum.csproj
index 8fdb07254..9d0721ed1 100644
--- a/src/Perpetuum/Perpetuum.csproj
+++ b/src/Perpetuum/Perpetuum.csproj
@@ -20,7 +20,7 @@
3.5
- v4.6.1
+ v4.6.2
false
publish\
@@ -70,25 +70,70 @@
x64
-
- ..\..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll
+
+ ..\..\packages\Discord.Net.Commands.3.17.4\lib\net461\Discord.Net.Commands.dll
+
+
+ ..\..\packages\Discord.Net.Core.3.17.4\lib\net461\Discord.Net.Core.dll
+
+
+ ..\..\packages\Discord.Net.Interactions.3.17.4\lib\net461\Discord.Net.Interactions.dll
+
+
+ ..\..\packages\Discord.Net.Rest.3.17.4\lib\net461\Discord.Net.Rest.dll
+
+
+ ..\..\packages\Discord.Net.Webhook.3.17.4\lib\netstandard2.0\Discord.Net.Webhook.dll
+
+
+ ..\..\packages\Discord.Net.WebSocket.3.17.4\lib\net461\Discord.Net.WebSocket.dll
+
+
+ ..\..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\netstandard2.0\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+ ..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.8.0.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
+
+
+ ..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll
-
- ..\..\packages\System.Collections.Immutable.1.4.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
+ ..\..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+ ..\..\packages\System.Collections.Immutable.9.0.5\lib\netstandard2.0\System.Collections.Immutable.dll
+
+ ..\..\packages\System.Interactive.Async.6.0.1\lib\netstandard2.0\System.Interactive.Async.dll
+
+
+ ..\..\packages\System.Linq.Async.6.0.1\lib\netstandard2.0\System.Linq.Async.dll
+
+
+ ..\..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll
+
-
- ..\..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll
+
+ ..\..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\..\packages\System.Reactive.6.0.1\lib\netstandard2.0\System.Reactive.dll
+
+ ..\..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
-
- ..\..\packages\System.ValueTuple.4.4.0\lib\net461\System.ValueTuple.dll
+
+ ..\..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll
@@ -345,15 +390,19 @@
+
+
+
+
@@ -766,9 +815,15 @@
+
+
+
+
+
+
@@ -876,9 +931,7 @@
-
-
@@ -1411,6 +1464,7 @@
+
diff --git a/src/Perpetuum/Robots/OverheatHandler.cs b/src/Perpetuum/Robots/OverheatHandler.cs
index b75e692a2..0f67237d3 100644
--- a/src/Perpetuum/Robots/OverheatHandler.cs
+++ b/src/Perpetuum/Robots/OverheatHandler.cs
@@ -29,7 +29,7 @@ public OverheatHandler(Robot robot)
private double oldOverheatValue;
private readonly object @lock = new object();
- public event EffectEventHandler EffectChanged;
+ //public event EffectEventHandler EffectChanged;
public void Increase(double value = 1)
{
diff --git a/src/Perpetuum/Services/Channels/ChannelManager.cs b/src/Perpetuum/Services/Channels/ChannelManager.cs
index bc04d602f..a20124a46 100644
--- a/src/Perpetuum/Services/Channels/ChannelManager.cs
+++ b/src/Perpetuum/Services/Channels/ChannelManager.cs
@@ -1,4 +1,5 @@
-using Perpetuum.Accounting.Characters;
+using Newtonsoft.Json;
+using Perpetuum.Accounting.Characters;
using Perpetuum.Common.Loggers;
using Perpetuum.Host.Requests;
using Perpetuum.Services.Channels.ChatCommands;
@@ -7,12 +8,17 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
+using System.Net.Http;
+using System.Text;
using System.Threading;
+using System.Threading.Tasks;
namespace Perpetuum.Services.Channels
{
public class ChannelManager : IChannelManager
{
+ private const string HelpChat = "regchannel_help";
+
private readonly ISessionManager _sessionManager;
private readonly IChannelRepository _channelRepository;
private readonly IChannelMemberRepository _memberRepository;
@@ -20,8 +26,16 @@ public class ChannelManager : IChannelManager
private readonly ChannelLoggerFactory _channelLoggerFactory;
private readonly ConcurrentDictionary _channels = new ConcurrentDictionary();
private readonly AdminCommandRouter _adminCommand;
-
- public ChannelManager(ISessionManager sessionManager, IChannelRepository channelRepository, IChannelMemberRepository memberRepository, IChannelBanRepository banRepository, ChannelLoggerFactory channelLoggerFactory, AdminCommandRouter adminCommand)
+ private readonly GlobalConfiguration _globalConfiguration;
+
+ public ChannelManager(
+ ISessionManager sessionManager,
+ IChannelRepository channelRepository,
+ IChannelMemberRepository memberRepository,
+ IChannelBanRepository banRepository,
+ ChannelLoggerFactory channelLoggerFactory,
+ AdminCommandRouter adminCommand,
+ GlobalConfiguration globalConfiguration)
{
_sessionManager = sessionManager;
_sessionManager.SessionAdded += OnSessionAdded;
@@ -36,6 +50,8 @@ public ChannelManager(ISessionManager sessionManager, IChannelRepository channel
{
_channels[channel.Name] = channel;
}
+
+ _globalConfiguration = globalConfiguration;
}
private void OnSessionAdded(ISession session)
@@ -296,8 +312,35 @@ public void Talk(string channelName, Character sender, string message, IRequest
else
{
channel.SendMessageToAll(_sessionManager, sender, message);
- }
+ if (channel.Name == HelpChat)
+ {
+ // Sending message to discord
+
+ string webhookId = _globalConfiguration.WebHookId;
+ string webhookOAuth = _globalConfiguration.WebHookOAuth;
+
+ if (string.IsNullOrEmpty(webhookId) || string.IsNullOrEmpty(webhookOAuth))
+ {
+ return;
+ }
+
+ string url = $"https://discord.com/api/webhooks/{webhookId}/{webhookOAuth}";
+ HttpClient httpClient = new HttpClient();
+ DiscordPayload payload = new DiscordPayload
+ {
+ content = $"**<{sender.Nick}>**: {message}",
+ };
+
+ string json = JsonConvert.SerializeObject(payload);
+ StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
+
+ Task.Run(async () =>
+ {
+ HttpResponseMessage response = await httpClient.PostAsync(url, content);
+ });
+ }
+ }
}
public void Announcement(string channelName, Character sender, string message)
@@ -419,4 +462,10 @@ public IEnumerable GetAllChannels()
return _channels.Values;
}
}
+
+ internal class DiscordPayload
+ {
+ public DateTime Timestamp { get; set; }
+ public string content { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Perpetuum/Services/EventServices/EventListenerService.cs b/src/Perpetuum/Services/EventServices/EventListenerService.cs
index 7c13617fb..a6e196fe2 100644
--- a/src/Perpetuum/Services/EventServices/EventListenerService.cs
+++ b/src/Perpetuum/Services/EventServices/EventListenerService.cs
@@ -1,10 +1,13 @@
-using Perpetuum.Threading.Process;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
+using Discord;
+using Discord.WebSocket;
using Perpetuum.Services.EventServices.EventMessages;
using Perpetuum.Services.EventServices.EventProcessors;
+using Perpetuum.Threading.Process;
using Perpetuum.Timers;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Threading.Tasks;
namespace Perpetuum.Services.EventServices
{
@@ -17,10 +20,19 @@ public class EventListenerService : Process
private readonly IDictionary> _observers;
private readonly ConcurrentQueue _queue;
- public EventListenerService()
+ private readonly DiscordSocketClient _client;
+ private readonly GlobalConfiguration _globalConfiguration;
+
+ public EventListenerService(GlobalConfiguration globalConfiguration)
{
_observers = new Dictionary>();
_queue = new ConcurrentQueue();
+
+ _client = new DiscordSocketClient(new DiscordSocketConfig
+ {
+ GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.MessageContent
+ });
+ _globalConfiguration = globalConfiguration;
}
///
@@ -36,9 +48,9 @@ public void NotifyListeners(IEventMessage message)
{
lock (_lock)
{
- if(_observers.TryGetValue(message.Type, out var list))
+ if (_observers.TryGetValue(message.Type, out IList list))
{
- foreach (var obs in list)
+ foreach (IEventProcessor obs in list)
{
obs.OnNext(message);
}
@@ -67,10 +79,10 @@ public void AttachListener(IEventProcessor observer)
public override void Update(TimeSpan time)
{
- var timer = new TimeKeeper(TimeSpan.FromSeconds(1));
+ TimeKeeper timer = new TimeKeeper(TimeSpan.FromSeconds(1));
while (!_queue.IsEmpty && !timer.Expired)
{
- if (_queue.TryDequeue(out var message))
+ if (_queue.TryDequeue(out IEventMessage message))
{
NotifyListeners(message);
}
@@ -79,12 +91,63 @@ public override void Update(TimeSpan time)
public override void Stop()
{
+ Task.Run(async () =>
+ {
+ await _client.LogoutAsync();
+ await _client.StopAsync();
+ });
+
+ _client.Log -= Log;
+ _client.MessageReceived -= OnMessageReceived;
+
base.Stop();
}
public override void Start()
{
base.Start();
+
+ string discordBotToken = _globalConfiguration.DiscordBotToken;
+
+ if (!string.IsNullOrEmpty(discordBotToken))
+ {
+ _client.Log += Log;
+ _client.MessageReceived += OnMessageReceived;
+
+ // Run the async logic in the background
+ Task.Run(async () =>
+ {
+ await _client.LoginAsync(TokenType.Bot, discordBotToken);
+ await _client.StartAsync();
+ });
+ }
+ }
+
+ private Task OnMessageReceived(SocketMessage message)
+ {
+ ulong.TryParse(_globalConfiguration.OpHelpChannelId, out ulong channelId);
+
+ if (!message.Author.IsBot && message.Channel.Id == channelId && !string.IsNullOrEmpty(message.Content))
+ {
+ string nick = message.Author.GlobalName;
+
+ if (message.Author is SocketGuildUser guildUser &&
+ !string.IsNullOrEmpty(guildUser.DisplayName))
+ {
+ nick = guildUser.DisplayName;
+ }
+
+ PublishMessage(new DiscordIntegrationMessage(nick, message.Content));
+ }
+
+ return Task.CompletedTask;
+ }
+
+ private Task Log(LogMessage msg)
+ {
+ // There has to be logging logic but meh.
+
+ return Task.CompletedTask;
}
}
}
diff --git a/src/Perpetuum/Services/EventServices/EventMessages/DiscordIntegrationMessage.cs b/src/Perpetuum/Services/EventServices/EventMessages/DiscordIntegrationMessage.cs
new file mode 100644
index 000000000..10622a2be
--- /dev/null
+++ b/src/Perpetuum/Services/EventServices/EventMessages/DiscordIntegrationMessage.cs
@@ -0,0 +1,17 @@
+namespace Perpetuum.Services.EventServices.EventMessages
+{
+ ///
+ /// Message for sending a message from Discord to the Game
+ ///
+ public class DiscordIntegrationMessage : IEventMessage
+ {
+ public EventType Type => EventType.DiscordIntegration;
+ public string Nick { get; private set; }
+ public string Message { get; private set; }
+ public DiscordIntegrationMessage(string nick, string message)
+ {
+ Nick = nick;
+ Message = message;
+ }
+ }
+}
diff --git a/src/Perpetuum/Services/EventServices/EventMessages/SapAttackersSpawnMessage.cs b/src/Perpetuum/Services/EventServices/EventMessages/SapAttackersSpawnMessage.cs
new file mode 100644
index 000000000..f34a844e9
--- /dev/null
+++ b/src/Perpetuum/Services/EventServices/EventMessages/SapAttackersSpawnMessage.cs
@@ -0,0 +1,25 @@
+using Perpetuum.Zones.Intrusion;
+
+namespace Perpetuum.Services.EventServices.EventMessages
+{
+ public class SapAttackersSpawnMessage : IEventMessage
+ {
+ public EventType Type => EventType.NpcSapAttackers;
+
+ public SapState SapState { get; }
+
+ public SAP Sap { get; }
+
+ public int ZoneId { get; }
+
+ public int Stability { get; set; }
+
+ public SapAttackersSpawnMessage(SAP sap, SapState sapState, int zoneID, int stability)
+ {
+ ZoneId = zoneID;
+ Sap = sap;
+ SapState = sapState;
+ Stability = stability;
+ }
+ }
+}
diff --git a/src/Perpetuum/Services/EventServices/EventProcessors/DiscordIntegrationHandler.cs b/src/Perpetuum/Services/EventServices/EventProcessors/DiscordIntegrationHandler.cs
new file mode 100644
index 000000000..24920c494
--- /dev/null
+++ b/src/Perpetuum/Services/EventServices/EventProcessors/DiscordIntegrationHandler.cs
@@ -0,0 +1,34 @@
+using Perpetuum.Accounting.Characters;
+using Perpetuum.Services.Channels;
+using Perpetuum.Services.EventServices.EventMessages;
+
+namespace Perpetuum.Services.EventServices.EventProcessors
+{
+ ///
+ /// Discord Integration EventProcessor
+ ///
+ public class DiscordIntegrationHandler : EventProcessor
+ {
+ private readonly IChannelManager _channelManager;
+ private const string SENDER_CHARACTER_NICKNAME = "Discord";
+ private const string HelpChat = "regchannel_help";
+ private readonly Character _announcer;
+
+ public DiscordIntegrationHandler(IChannelManager channelManager)
+ {
+ _announcer = Character.GetByNick(SENDER_CHARACTER_NICKNAME);
+ _channelManager = channelManager;
+ }
+
+ public override EventType Type => EventType.DiscordIntegration;
+ public override void HandleMessage(IEventMessage message)
+ {
+ if (message is DiscordIntegrationMessage discordMessage)
+ {
+ string chatMessage = $"{discordMessage.Nick}: {discordMessage.Message}";
+
+ _channelManager.Announcement(HelpChat, _announcer, chatMessage);
+ }
+ }
+ }
+}
diff --git a/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/NpcReinforcementSpawner.cs b/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/NpcReinforcementSpawner.cs
index dc8788f37..984ee8731 100644
--- a/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/NpcReinforcementSpawner.cs
+++ b/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/NpcReinforcementSpawner.cs
@@ -6,6 +6,7 @@
using Perpetuum.Zones.NpcSystem.Flocks;
using Perpetuum.Zones.NpcSystem.Presences;
using Perpetuum.Zones.NpcSystem.Reinforcements;
+using Perpetuum.Zones.NpcSystem.SapAttackers;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -14,16 +15,19 @@ namespace Perpetuum.Services.EventServices.EventProcessors.NpcSpawnEventHandlers
{
public class NpcReinforcementSpawner : NpcSpawnEventHandler
{
- protected override TimeSpan SPAWN_DELAY { get { return TimeSpan.FromSeconds(5); } }
- protected override TimeSpan SPAWN_LIFETIME { get { return TimeSpan.FromMinutes(30); } }
- protected override int MAX_SPAWN_DIST { get { return 15; } }
+ protected override TimeSpan SPAWN_DELAY => TimeSpan.FromSeconds(5);
+ protected override TimeSpan SPAWN_LIFETIME => TimeSpan.FromMinutes(30);
+ protected override int MAX_SPAWN_DIST => 15;
public override EventType Type => EventType.NpcReinforce;
- private readonly IDictionary _reinforcementsByNpc = new Dictionary();
- public NpcReinforcementSpawner(IZone zone, INpcReinforcementsRepository reinforcementsRepo) : base(zone, reinforcementsRepo) { }
+ private readonly IDictionary _reinforcementsByNpc = new Dictionary();
+ public NpcReinforcementSpawner(
+ IZone zone,
+ INpcReinforcementsRepository reinforcementsRepo,
+ ISapAttackersRepository sapAttackersRepository) : base(zone, reinforcementsRepo, sapAttackersRepository) { }
- protected override IEnumerable GetActiveReinforcments(Presence presence)
+ protected override IEnumerable GetActiveReinforcments(Presence presence)
{
return _reinforcementsByNpc.Where(p => p.Value.HasActivePresence(presence)).Select(p => p.Value);
}
@@ -33,21 +37,23 @@ protected override bool CheckMessage(IEventMessage inMsg, out NpcReinforcementsM
if (inMsg is NpcReinforcementsMessage message && _zone.Id == message.ZoneId)
{
msg = message;
+
return true;
}
else
{
msg = null;
+
return false;
}
}
protected override void CheckReinforcements(NpcReinforcementsMessage msg)
{
- var info = msg.SmartCreature.BossInfo;
+ NpcBossInfo info = msg.SmartCreature.BossInfo;
if (!_reinforcementsByNpc.ContainsKey(info))
{
- var reinforcements = _npcReinforcementsRepo.CreateNpcBossAddSpawn(info, msg.ZoneId);
+ INpcPresences reinforcements = _npcReinforcementsRepo.CreateNpcBossAddSpawn(info, msg.ZoneId);
_reinforcementsByNpc.Add(info, reinforcements);
}
}
@@ -56,54 +62,55 @@ protected override bool CheckState(NpcReinforcementsMessage msg)
{
if (msg.SmartCreature.BossInfo.IsDead)
{
- CleanupAllReinforcements(msg);
+ CleanupAllAttackers(msg);
+
return true;
}
UpdateAggro(msg);
+
return false;
}
private void UpdateAggro(NpcReinforcementsMessage msg)
{
- var info = msg.SmartCreature.BossInfo;
+ NpcBossInfo info = msg.SmartCreature.BossInfo;
if (_reinforcementsByNpc.ContainsKey(info))
{
- var activeWaves = _reinforcementsByNpc[info].GetAllActiveWaves().Where(w => w.ActivePresence != null);
- foreach (var wave in activeWaves)
+ IEnumerable activeWaves = _reinforcementsByNpc[info].GetAllActivePresences().Where(w => w.ActivePresence != null);
+ foreach (INpcPresence wave in activeWaves)
{
SpreadAggro(wave.ActivePresence, msg.SmartCreature);
}
}
}
- protected override void CleanupAllReinforcements(NpcReinforcementsMessage msg)
+ protected override void CleanupAllAttackers(NpcReinforcementsMessage msg)
{
- var info = msg.SmartCreature.BossInfo;
+ NpcBossInfo info = msg.SmartCreature.BossInfo;
if (_reinforcementsByNpc.ContainsKey(info))
{
- var activeWaves = _reinforcementsByNpc[info].GetAllActiveWaves();
- foreach (var wave in activeWaves)
+ INpcPresence[] activeWaves = _reinforcementsByNpc[info].GetAllActivePresences();
+ foreach (INpcPresence wave in activeWaves)
{
ExpireWave(wave);
}
+
_reinforcementsByNpc.Remove(info);
}
}
protected override Position FindSpawnPosition(NpcReinforcementsMessage msg, int maxRange)
{
- var finder = new RandomWalkableAroundPositionFinder(_zone, msg.SmartCreature.CurrentPosition, maxRange);
- if (finder.Find(out Position result))
- {
- return result;
- }
- return msg.SmartCreature.CurrentPosition;
+ RandomWalkableAroundPositionFinder finder = new RandomWalkableAroundPositionFinder(_zone, msg.SmartCreature.CurrentPosition, maxRange);
+
+ return finder.Find(out Position result) ? result : msg.SmartCreature.CurrentPosition;
}
- protected override INpcReinforcementWave GetNextWave(NpcReinforcementsMessage msg)
+ protected override INpcPresence GetNextWave(NpcReinforcementsMessage msg)
{
- var npc = msg.SmartCreature;
- var percent = 1.0 - npc.ArmorPercentage;
+ SmartCreature npc = msg.SmartCreature;
+ double percent = 1.0 - npc.ArmorPercentage;
+
return _reinforcementsByNpc[npc.BossInfo].GetNextPresence(percent);
}
@@ -114,9 +121,9 @@ protected override void OnSpawning(Presence pres, NpcReinforcementsMessage msg)
private void SpreadAggro(Presence presenceToAggro, SmartCreature smartCreatureWithAggro)
{
- foreach (var npc in presenceToAggro.Flocks.GetMembers())
+ foreach (Npc npc in presenceToAggro.Flocks.GetMembers())
{
- foreach (var threat in smartCreatureWithAggro.ThreatManager.Hostiles)
+ foreach (Zones.NpcSystem.ThreatManaging.Hostile threat in smartCreatureWithAggro.ThreatManager.Hostiles)
{
npc.AddDirectThreat(threat.Unit, threat.Threat + FastRandom.NextDouble(5, 10));
}
diff --git a/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/NpcSpawnEventHandler.cs b/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/NpcSpawnEventHandler.cs
index f89c735a5..f9c41f6f0 100644
--- a/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/NpcSpawnEventHandler.cs
+++ b/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/NpcSpawnEventHandler.cs
@@ -2,8 +2,10 @@
using Perpetuum.Log;
using Perpetuum.Services.EventServices.EventMessages;
using Perpetuum.Zones;
+using Perpetuum.Zones.NpcSystem;
using Perpetuum.Zones.NpcSystem.Presences;
using Perpetuum.Zones.NpcSystem.Reinforcements;
+using Perpetuum.Zones.NpcSystem.SapAttackers;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
@@ -22,13 +24,15 @@ public abstract class NpcSpawnEventHandler : EventProcessor where T : IEventM
protected readonly IZone _zone;
protected readonly INpcReinforcementsRepository _npcReinforcementsRepo;
- public NpcSpawnEventHandler(IZone zone, INpcReinforcementsRepository reinforcementsRepo)
+ protected readonly ISapAttackersRepository _npcSapAttackersRepo;
+ public NpcSpawnEventHandler(IZone zone, INpcReinforcementsRepository reinforcementsRepo, ISapAttackersRepository sapAttackersRepository)
{
_zone = zone;
_npcReinforcementsRepo = reinforcementsRepo;
+ _npcSapAttackersRepo = sapAttackersRepository;
}
- protected abstract IEnumerable GetActiveReinforcments(Presence presence);
+ protected abstract IEnumerable GetActiveReinforcments(Presence presence);
protected abstract bool CheckMessage(IEventMessage inMsg, out T msg);
@@ -36,11 +40,11 @@ public NpcSpawnEventHandler(IZone zone, INpcReinforcementsRepository reinforceme
protected abstract bool CheckState(T msg);
- protected abstract void CleanupAllReinforcements(T msg);
+ protected abstract void CleanupAllAttackers(T msg);
protected abstract Position FindSpawnPosition(T msg, int maxRange);
- protected abstract INpcReinforcementWave GetNextWave(T msg);
+ protected abstract INpcPresence GetNextWave(T msg);
protected virtual void OnSpawning(Presence pres, T msg) { }
@@ -55,9 +59,9 @@ protected void DoBeams(Position beamLocation)
_zone.CreateBeam(BeamType.teleport_storm, b => b.WithPosition(beamLocation).WithDuration(SPAWN_DELAY));
}
- protected void DoSpawning(INpcReinforcementWave wave, Position homePosition, Position spawnPosition, T msg)
+ protected void DoSpawning(INpcPresence wave, Position homePosition, Position spawnPosition, T msg)
{
- var pres = _zone.AddDynamicPresenceToPosition(wave.PresenceId, homePosition, spawnPosition, SPAWN_LIFETIME);
+ DynamicPresenceExtended pres = _zone.AddDynamicPresenceToPosition(wave.PresenceId, homePosition, spawnPosition, SPAWN_LIFETIME);
OnSpawning(pres, msg);
pres.PresenceExpired += OnPresenceExpired;
wave.SetActivePresence(pres);
@@ -65,15 +69,15 @@ protected void DoSpawning(INpcReinforcementWave wave, Position homePosition, Pos
protected void OnPresenceExpired(Presence presence)
{
- var activeReinforcements = GetActiveReinforcments(presence);
- foreach (var reinforcements in activeReinforcements)
+ IEnumerable activeReinforcements = GetActiveReinforcments(presence);
+ foreach (Zones.NpcSystem.INpcPresences reinforcements in activeReinforcements)
{
- var wave = reinforcements.GetActiveWaveOfPresence(presence);
+ INpcPresence wave = reinforcements.GetActivePresence(presence);
ExpireWave(wave);
}
}
- protected void ExpireWave(INpcReinforcementWave wave)
+ protected void ExpireWave(INpcPresence wave)
{
wave.ActivePresence.PresenceExpired -= OnPresenceExpired;
wave.DeactivatePresence();
@@ -86,22 +90,30 @@ public override void HandleMessage(IEventMessage value)
if (CheckMessage(value, out T msg))
{
if (CheckState(msg))
+ {
return;
+ }
if (_spawning)
+ {
return;
+ }
CheckReinforcements(msg);
- var wave = GetNextWave(msg);
+ INpcPresence wave = GetNextWave(msg);
if (wave == null)
+ {
return; // Presence not found for this message state or already spawned
+ }
- var spawnPos = FindSpawnPosition(msg, MAX_SPAWN_DIST);
+ Position spawnPos = FindSpawnPosition(msg, MAX_SPAWN_DIST);
if (spawnPos == Position.Empty)
+ {
return; // Failed to find valid spawn location, try again on next cycle
+ }
- var homePos = GetHomePos(msg, spawnPos);
+ Position homePos = GetHomePos(msg, spawnPos);
DoBeams(homePos);
diff --git a/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/OreNPCSpawner.cs b/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/OreNPCSpawner.cs
index 770a7906c..eb55e5c5b 100644
--- a/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/OreNPCSpawner.cs
+++ b/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/OreNPCSpawner.cs
@@ -1,8 +1,10 @@
using Perpetuum.Services.EventServices.EventMessages;
using Perpetuum.Zones;
using Perpetuum.Zones.Finders.PositionFinders;
+using Perpetuum.Zones.NpcSystem;
using Perpetuum.Zones.NpcSystem.Presences;
using Perpetuum.Zones.NpcSystem.Reinforcements;
+using Perpetuum.Zones.NpcSystem.SapAttackers;
using Perpetuum.Zones.Terrains.Materials.Minerals;
using System;
using System.Collections.Generic;
@@ -23,15 +25,19 @@ public class OreNpcSpawner : NpcSpawnEventHandler
public override EventType Type => EventType.NpcOre;
- private readonly IDictionary _reinforcementsByNode = new Dictionary();
+ private readonly IDictionary _reinforcementsByNode = new Dictionary();
private readonly IEnumerable _mineralConfigs;
- public OreNpcSpawner(IZone zone, INpcReinforcementsRepository reinforcementsRepo, IMineralConfigurationReader mineralConfigurationReader) : base(zone, reinforcementsRepo)
+ public OreNpcSpawner(
+ IZone zone,
+ INpcReinforcementsRepository reinforcementsRepo,
+ ISapAttackersRepository sapAttackersRepository,
+ IMineralConfigurationReader mineralConfigurationReader) : base(zone, reinforcementsRepo, sapAttackersRepository)
{
_mineralConfigs = mineralConfigurationReader.ReadAll().Where(c => c.ZoneId == zone.Id);
}
- protected override IEnumerable GetActiveReinforcments(Presence presence)
+ protected override IEnumerable GetActiveReinforcments(Presence presence)
{
return _reinforcementsByNode.Where(p => p.Value.HasActivePresence(presence)).Select(p => p.Value);
}
@@ -41,11 +47,13 @@ protected override bool CheckMessage(IEventMessage inMsg, out OreNpcSpawnMessage
if (inMsg is OreNpcSpawnMessage message && _zone.Id == message.ZoneId)
{
msg = message;
+
return true;
}
else
{
msg = null;
+
return false;
}
}
@@ -55,7 +63,7 @@ protected override void CheckReinforcements(OreNpcSpawnMessage msg)
MineralNode node = msg.Node;
if (!_reinforcementsByNode.ContainsKey(node))
{
- INpcReinforcements oreSpawn = _npcReinforcementsRepo.CreateOreNPCSpawn(node.Type, msg.ZoneId);
+ INpcPresences oreSpawn = _npcReinforcementsRepo.CreateOreNPCSpawn(node.Type, msg.ZoneId);
_reinforcementsByNode.Add(node, oreSpawn);
}
}
@@ -64,22 +72,25 @@ protected override bool CheckState(OreNpcSpawnMessage msg)
{
if (msg.NodeState == OreNodeState.Removed)
{
- CleanupAllReinforcements(msg);
+ CleanupAllAttackers(msg);
+
return true;
}
+
return false;
}
- protected override void CleanupAllReinforcements(OreNpcSpawnMessage msg)
+ protected override void CleanupAllAttackers(OreNpcSpawnMessage msg)
{
MineralNode node = msg.Node;
if (_reinforcementsByNode.ContainsKey(node))
{
- INpcReinforcementWave[] activeWaves = _reinforcementsByNode[node].GetAllActiveWaves();
- foreach (INpcReinforcementWave wave in activeWaves)
+ INpcPresence[] activeWaves = _reinforcementsByNode[node].GetAllActivePresences();
+ foreach (INpcPresence wave in activeWaves)
{
ExpireWave(wave);
}
+
_reinforcementsByNode.Remove(node);
}
}
@@ -88,6 +99,7 @@ protected override Position FindSpawnPosition(OreNpcSpawnMessage msg, int maxRan
{
Position fieldCenter = msg.Node.Area.Center.ToPosition();
RandomWalkableOnCircle finder = new RandomWalkableOnCircle(_zone, fieldCenter, maxRange, MIN_SPAWN_DIST_TOLERANCE);
+
return finder.Find(out Position result) ? result : Position.Empty;
}
@@ -96,13 +108,15 @@ private double ComputeFieldPercentConsumed(MineralNode node)
int current = Convert.ToInt32(node.GetTotalAmount());
int total = _mineralConfigs.Single(c => c.Type == node.Type).TotalAmountPerNode;
double percent = 1.0 - (current / (double)total).Clamp();
+
return percent;
}
- protected override INpcReinforcementWave GetNextWave(OreNpcSpawnMessage msg)
+ protected override INpcPresence GetNextWave(OreNpcSpawnMessage msg)
{
MineralNode node = msg.Node;
double percent = ComputeFieldPercentConsumed(node);
+
return _reinforcementsByNode[node].GetNextPresence(percent);
}
diff --git a/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/SapAttackerSpawner.cs b/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/SapAttackerSpawner.cs
new file mode 100644
index 000000000..30274858d
--- /dev/null
+++ b/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/SapAttackerSpawner.cs
@@ -0,0 +1,107 @@
+using Perpetuum.Services.EventServices.EventMessages;
+using Perpetuum.Zones;
+using Perpetuum.Zones.Finders.PositionFinders;
+using Perpetuum.Zones.NpcSystem;
+using Perpetuum.Zones.NpcSystem.Presences;
+using Perpetuum.Zones.NpcSystem.Reinforcements;
+using Perpetuum.Zones.NpcSystem.SapAttackers;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Perpetuum.Services.EventServices.EventProcessors.NpcSpawnEventHandlers
+{
+ public class SapAttackerSpawner : NpcSpawnEventHandler
+ {
+ protected override TimeSpan SPAWN_DELAY => TimeSpan.FromSeconds(10);
+ protected override TimeSpan SPAWN_LIFETIME => TimeSpan.FromHours(3);
+ protected override int MAX_SPAWN_DIST => 100;
+
+ private const int MIN_SPAWN_DIST_TOLERANCE = 30;
+
+ public override EventType Type => EventType.NpcSapAttackers;
+
+ private readonly IDictionary _attackersBySap = new Dictionary();
+
+ public SapAttackerSpawner(
+ IZone zone,
+ INpcReinforcementsRepository reinforcementsRepo,
+ ISapAttackersRepository sapAttackersRepository) : base(zone, reinforcementsRepo, sapAttackersRepository)
+ {
+ }
+
+ protected override IEnumerable GetActiveReinforcments(Presence presence)
+ {
+ return _attackersBySap.Where(p => p.Value.HasActivePresence(presence)).Select(p => p.Value);
+ }
+
+ protected override bool CheckMessage(IEventMessage inMsg, out SapAttackersSpawnMessage msg)
+ {
+ if (inMsg is SapAttackersSpawnMessage message && _zone.Id == message.ZoneId)
+ {
+ msg = message;
+
+ return true;
+ }
+ else
+ {
+ msg = null;
+
+ return false;
+ }
+ }
+
+ protected override void CheckReinforcements(SapAttackersSpawnMessage msg)
+ {
+ if (!_attackersBySap.ContainsKey(msg.Sap.Definition))
+ {
+ INpcPresences oreSpawn = _npcSapAttackersRepo.CreateSapAttackersSpawn(msg.Sap.Definition, msg.ZoneId);
+ _attackersBySap.Add(msg.Sap.Definition, oreSpawn);
+ }
+ }
+
+ protected override bool CheckState(SapAttackersSpawnMessage msg)
+ {
+ if (msg.SapState == SapState.Closed || msg.SapState == SapState.Completed)
+ {
+ CleanupAllAttackers(msg);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ protected override void CleanupAllAttackers(SapAttackersSpawnMessage msg)
+ {
+ if (_attackersBySap.ContainsKey(msg.Sap.Definition))
+ {
+ INpcPresence[] activeWaves = _attackersBySap[msg.Sap.Definition].GetAllActivePresences();
+ foreach (INpcPresence wave in activeWaves)
+ {
+ ExpireWave(wave);
+ }
+
+ _attackersBySap.Remove(msg.Sap.Definition);
+ }
+ }
+
+ protected override Position FindSpawnPosition(SapAttackersSpawnMessage msg, int maxRange)
+ {
+ Position fieldCenter = msg.Sap.CurrentPosition;
+ RandomWalkableOnCircle finder = new RandomWalkableOnCircle(_zone, fieldCenter, maxRange, MIN_SPAWN_DIST_TOLERANCE);
+
+ return finder.Find(out Position result) ? result : Position.Empty;
+ }
+
+ protected override Position GetHomePos(SapAttackersSpawnMessage msg, Position spawnPos)
+ {
+ return msg.Sap.CurrentPosition;
+ }
+
+ protected override INpcPresence GetNextWave(SapAttackersSpawnMessage msg)
+ {
+ return _attackersBySap[msg.Sap.Definition].GetNextPresence(msg.Stability);
+ }
+ }
+}
diff --git a/src/Perpetuum/Services/EventServices/EventType.cs b/src/Perpetuum/Services/EventServices/EventType.cs
index 85de191c3..6c90400fd 100644
--- a/src/Perpetuum/Services/EventServices/EventType.cs
+++ b/src/Perpetuum/Services/EventServices/EventType.cs
@@ -12,5 +12,7 @@ public enum EventType
NpcReinforce,
Environmental,
PortalSpawn,
+ NpcSapAttackers,
+ DiscordIntegration,
}
}
diff --git a/src/Perpetuum/Threading/Process/ProcessManager.cs b/src/Perpetuum/Threading/Process/ProcessManager.cs
index 189b872b1..7f4294ec0 100644
--- a/src/Perpetuum/Threading/Process/ProcessManager.cs
+++ b/src/Perpetuum/Threading/Process/ProcessManager.cs
@@ -1,9 +1,9 @@
+using Perpetuum.Log;
+using Perpetuum.Timers;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
-using Perpetuum.Log;
-using Perpetuum.Timers;
namespace Perpetuum.Threading.Process
{
@@ -23,7 +23,7 @@ public ProcessManager(TimeSpan updateInterval)
public void AddProcess(IProcess process)
{
- ImmutableInterlocked.Update(ref _processes,p => p.Add(process));
+ ImmutableInterlocked.Update(ref _processes, p => p.Add(process));
}
public void RemoveProcess(IProcess process)
@@ -37,11 +37,13 @@ public void RemoveProcess(IProcess process)
public void Start()
{
if (_isRunning)
+ {
return;
+ }
_isRunning = true;
- foreach (var process in _processes)
+ foreach (IProcess process in _processes)
{
process.Start();
}
@@ -68,7 +70,7 @@ public void Stop()
}
}
- foreach (var process in _processes)
+ foreach (IProcess process in _processes)
{
StopProcess(process);
}
@@ -88,18 +90,18 @@ private static void StopProcess(IProcess process)
private void UpdateLoop()
{
- var last = GlobalTimer.Elapsed;
- var prevSleepTime = TimeSpan.Zero;
+ TimeSpan last = GlobalTimer.Elapsed;
+ TimeSpan prevSleepTime = TimeSpan.Zero;
while (_isRunning)
{
- var now = GlobalTimer.Elapsed;
- var elapsed = now - last;
+ TimeSpan now = GlobalTimer.Elapsed;
+ TimeSpan elapsed = now - last;
last = now;
try
{
- foreach (var process in _processes)
+ foreach (IProcess process in _processes)
{
process.Update(elapsed);
}
@@ -121,7 +123,9 @@ private void UpdateLoop()
Thread.Sleep(prevSleepTime);
}
else
+ {
prevSleepTime = TimeSpan.Zero;
+ }
}
}
}
diff --git a/src/Perpetuum/Units/Unit.cs b/src/Perpetuum/Units/Unit.cs
index 6145b5c25..df34a09d3 100644
--- a/src/Perpetuum/Units/Unit.cs
+++ b/src/Perpetuum/Units/Unit.cs
@@ -19,6 +19,7 @@
using Perpetuum.Zones.Effects;
using Perpetuum.Zones.Eggs;
using Perpetuum.Zones.Gates;
+using Perpetuum.Zones.Intrusion;
using Perpetuum.Zones.Locking;
using Perpetuum.Zones.NpcSystem;
using Perpetuum.Zones.PBS;
@@ -925,6 +926,11 @@ internal virtual bool IsHostile(MobileTeleport teleport)
return false;
}
+ internal virtual bool IsHostile(SAP sap)
+ {
+ return false;
+ }
+
public void StopMoving()
{
CurrentSpeed = 0;
diff --git a/src/Perpetuum/Zones/Intrusion/DestructionSAP.cs b/src/Perpetuum/Zones/Intrusion/DestructionSAP.cs
index 12328834e..ddbcc50f3 100644
--- a/src/Perpetuum/Zones/Intrusion/DestructionSAP.cs
+++ b/src/Perpetuum/Zones/Intrusion/DestructionSAP.cs
@@ -1,6 +1,7 @@
using Perpetuum.ExportedTypes;
using Perpetuum.Units;
using Perpetuum.Zones.DamageProcessors;
+using Perpetuum.Zones.NpcSystem;
using System.Linq;
namespace Perpetuum.Zones.Intrusion
@@ -18,6 +19,13 @@ protected override void OnDamageTaken(Unit source, DamageTakenEventArgs e)
{
base.OnDamageTaken(source, e);
+ if (source is Npc)
+ {
+ IncrementNpcScore((int)e.TotalDamage);
+
+ return;
+ }
+
Players.Player player = Zone.ToPlayerOrGetOwnerPlayer(source);
if (player == null)
{
diff --git a/src/Perpetuum/Zones/Intrusion/Outpost.cs b/src/Perpetuum/Zones/Intrusion/Outpost.cs
index 93b4a04b7..643f7f79b 100644
--- a/src/Perpetuum/Zones/Intrusion/Outpost.cs
+++ b/src/Perpetuum/Zones/Intrusion/Outpost.cs
@@ -35,6 +35,8 @@ public class Outpost : DockingBase
private const int PRODUCTION_BONUS_THRESHOLD = 100;
private const int MinAnnouncementDelay = 10;
private const int MaxAnnouncementDelay = 30;
+ private const int TimeUntilCultistsAttack = 1;
+ private const long NianiCorporationEid = 666;
private TimeRange _intrusionWaitTime => IntrusionWaitTime;
private readonly IEntityServices _entityServices;
@@ -43,6 +45,9 @@ public class Outpost : DockingBase
private static readonly ILookup _sapInfos;
private readonly EventListenerService _eventChannel;
private readonly OutpostDecay _decay;
+ private IntervalTimer _cultistsAttackTimer = null;
+
+ private SAP CurrentSap = null;
public static StabilityBonusThreshold[] StabilityBonusThresholds { get; private set; }
public static int DefenseNodesStabilityLimit { get; private set; }
@@ -164,6 +169,16 @@ protected override void OnUpdate(TimeSpan time)
base.OnUpdate(time);
_decay.OnUpdate(time);
+ if (CurrentSap != null && _cultistsAttackTimer != null)
+ {
+ _cultistsAttackTimer.Update(time);
+ if (_cultistsAttackTimer.Passed)
+ {
+ _cultistsAttackTimer = null;
+ _eventChannel.PublishMessage(new SapAttackersSpawnMessage(CurrentSap, SapState.Opened, Zone.Id, GetIntrusionSiteStability()));
+ }
+ }
+
if (!Enabled || IntrusionInProgress)
{
return;
@@ -284,6 +299,8 @@ private void DeploySAP()
sap.TakeOver += OnSAPTakeOver;
sap.TimeOut += OnSAPTimeOut;
sap.AddToZone(Zone, sapInfo.Position);
+ CurrentSap = sap;
+ _cultistsAttackTimer = new IntervalTimer(TimeSpan.FromMinutes(TimeUntilCultistsAttack));
const string insertCmd = "insert into intrusionsapdeploylog (siteeid,sapdefinition) values (@siteEid,@sapDefinition)";
Db.Query().CommandText(insertCmd).SetParameter("@siteEid", Eid).SetParameter("@sapDefinition", sap.Definition).ExecuteNonQuery();
@@ -372,6 +389,8 @@ private void OnSAPTakeOver(SAP sap)
TimeSpan randomDelay = FastRandom.NextTimeSpan(TimeSpan.FromMinutes(MinAnnouncementDelay), TimeSpan.FromMinutes(MaxAnnouncementDelay));
DateTime timeStamp = DateTime.UtcNow;
+ _eventChannel.PublishMessage(new SapAttackersSpawnMessage(CurrentSap, SapState.Completed, Zone.Id, GetIntrusionSiteStability()));
+
_ = Task.Delay(randomDelay).ContinueWith((t) =>
{
PublishMessage(new SapStateMessage(Eid, Name, SapState.Completed, DateTime.UtcNow));
@@ -566,6 +585,9 @@ private void OnSAPTimeOut(SAP sap)
TimeSpan randomDelay = FastRandom.NextTimeSpan(TimeSpan.FromMinutes(MinAnnouncementDelay), TimeSpan.FromMinutes(MaxAnnouncementDelay));
DateTime timeStamp = DateTime.UtcNow;
+ _eventChannel.PublishMessage(new SapAttackersSpawnMessage(CurrentSap, SapState.Closed, Zone.Id, GetIntrusionSiteStability()));
+ CurrentSap = null;
+
_ = Task.Delay(randomDelay).ContinueWith((t) =>
{
PublishMessage(new SapStateMessage(Eid, Name, SapState.Closed, DateTime.UtcNow));
diff --git a/src/Perpetuum/Zones/Intrusion/SAP.cs b/src/Perpetuum/Zones/Intrusion/SAP.cs
index 3d073d53f..640e7a9d3 100644
--- a/src/Perpetuum/Zones/Intrusion/SAP.cs
+++ b/src/Perpetuum/Zones/Intrusion/SAP.cs
@@ -1,4 +1,5 @@
using Perpetuum.Accounting.Characters;
+using Perpetuum.EntityFramework;
using Perpetuum.ExportedTypes;
using Perpetuum.Groups.Corporations;
using Perpetuum.Log;
@@ -29,6 +30,12 @@ public SAPPlayerInfo(Player player)
corporationEid = player.CorporationEid;
}
+ public SAPPlayerInfo(Character character, long corporationEid)
+ {
+ this.character = character;
+ this.corporationEid = corporationEid;
+ }
+
public void IncrementScore(int value)
{
Interlocked.Add(ref score, value);
@@ -65,9 +72,14 @@ public IntrusionCorporationScore(long corporationEid, int score)
private static readonly TimeSpan _broadcastInfoInterval = TimeSpan.FromSeconds(2);
+ private readonly Character _npcAttackerCharacter;
+
private const int BROADCAST_INFO_TOP_SCORE_COUNT = 10;
private const int BROADCAST_INFO_RANGE = 100;
+ private const string NianiCultistNick = "Niani Cultist";
+ private const long NianiCorpEid = 666;
+
private readonly BeamType _enterBeamType;
private readonly BeamType _exitBeamType;
@@ -84,6 +96,7 @@ protected SAP(BeamType enterBeamType, BeamType exitBeamType)
{
_enterBeamType = enterBeamType;
_exitBeamType = exitBeamType;
+ _npcAttackerCharacter = Character.GetByNick(NianiCultistNick);
}
public void AddToZone(IZone zone, Position spawnPosition)
@@ -195,6 +208,21 @@ protected void IncrementPlayerScore(Player player, int score)
Logger.Info($"Intrusion SAP score updated. sap = {Eid} ({ED.Name}) player = {info.character.Id} score = {info.score}");
}
+ protected void IncrementNpcScore(int score)
+ {
+ SAPPlayerInfo info = ImmutableInterlocked.GetOrAdd(ref _playerInfos, _npcAttackerCharacter, c => new SAPPlayerInfo(_npcAttackerCharacter, NianiCorpEid));
+ info.IncrementScore(score);
+
+ if (MaxScore > 0 && info.score >= MaxScore)
+ {
+ OnTakeOver();
+ }
+
+ ExtendTimerOnce();
+
+ Logger.Info($"Intrusion SAP score updated. sap = {Eid} ({ED.Name}) player = {info.character.Id} score = {info.score}");
+ }
+
private bool _firstSapAttempt = true;
private void ExtendTimerOnce()
{
@@ -363,14 +391,30 @@ public StabilityAffectingEvent ToStabilityAffectingEvent()
{
players.Add(player.character.GetPlayerRobotFromZone());
}
+
+ long winnerCorporationEid = GetWinnerCorporationEid();
StabilityAffectingEvent.StabilityAffectBuilder builder = StabilityAffectingEvent.Builder()
.WithOutpost(Site)
.WithSapDefinition(Definition)
.WithSapEntityID(Eid)
.WithPoints(StabilityChange)
.AddParticipants(players)
- .WithWinnerCorp(GetWinnerCorporationEid());
+ .WithWinnerCorp(winnerCorporationEid);
+
return builder.Build();
}
+
+ protected override bool IsHostileFor(Unit unit)
+ {
+ return unit.ED.Options.Faction == NpcSystem.Faction.Cultist;
+ }
+
+ public override void AcceptVisitor(IEntityVisitor visitor)
+ {
+ if (!TryAcceptVisitor(this, visitor))
+ {
+ base.AcceptVisitor(visitor);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Perpetuum/Zones/NpcSystem/AI/BodyPullThreatHelper.cs b/src/Perpetuum/Zones/NpcSystem/AI/BodyPullThreatHelper.cs
index 2751d5a11..0c0e82776 100644
--- a/src/Perpetuum/Zones/NpcSystem/AI/BodyPullThreatHelper.cs
+++ b/src/Perpetuum/Zones/NpcSystem/AI/BodyPullThreatHelper.cs
@@ -5,6 +5,7 @@
using Perpetuum.Services.RiftSystem;
using Perpetuum.Units;
using Perpetuum.Zones.Eggs;
+using Perpetuum.Zones.Intrusion;
using Perpetuum.Zones.NpcSystem.AI.Behaviors;
using Perpetuum.Zones.NpcSystem.ThreatManaging;
using Perpetuum.Zones.RemoteControl;
@@ -20,7 +21,8 @@ public class BodyPullThreatHelper :
IEntityVisitor,
IEntityVisitor,
IEntityVisitor,
- IEntityVisitor
+ IEntityVisitor,
+ IEntityVisitor
{
private readonly SmartCreature smartCreature;
@@ -140,6 +142,11 @@ public void Visit(SupportDrone supportDrone)
ProcessNpcThreats(supportDrone);
}
+ public void Visit(SAP entity)
+ {
+ ProcessNpcThreats(entity);
+ }
+
private void ProcessNpcThreats(Unit unit)
{
if (smartCreature.Behavior.Type != BehaviorType.RemoteControlledTurret &&
diff --git a/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/CombatDroneAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/CombatDroneAI.cs
index ebf358824..1a61cb5a0 100644
--- a/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/CombatDroneAI.cs
+++ b/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/CombatDroneAI.cs
@@ -5,7 +5,6 @@
using Perpetuum.Units;
using Perpetuum.Zones.Locking.Locks;
using Perpetuum.Zones.Movements;
-using Perpetuum.Zones.NpcSystem.TargettingStrategies;
using Perpetuum.Zones.RemoteControl;
using System;
using System.Collections.Generic;
@@ -26,7 +25,7 @@ public class CombatDroneAI : BaseAI
private readonly IntervalTimer primarySelectTimer = new IntervalTimer(UpdateFrequency);
private List moduleActivators;
private TimeSpan hostilesUpdateFrequency = TimeSpan.FromMilliseconds(UpdateFrequency);
- private readonly CombatPrimaryLockSelectionStrategySelector stratSelector;
+ //private readonly CombatPrimaryLockSelectionStrategySelector stratSelector;
private Position lastTargetPosition;
private PathMovement movement;
private PathMovement nextMovement;
diff --git a/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/GuardCombatDroneAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/GuardCombatDroneAI.cs
index 1f40265e2..0f5c2e1ad 100644
--- a/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/GuardCombatDroneAI.cs
+++ b/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/GuardCombatDroneAI.cs
@@ -40,7 +40,7 @@ public override void Update(TimeSpan time)
return;
}
- if (drone.HasCommandBotPrimaryLock() != null)
+ if (drone.HasCommandBotPrimaryLock())
{
ToAttackCombatDroneAI();
diff --git a/src/Perpetuum/Zones/NpcSystem/Creature.cs b/src/Perpetuum/Zones/NpcSystem/Creature.cs
index 79b43ee53..0b3205897 100644
--- a/src/Perpetuum/Zones/NpcSystem/Creature.cs
+++ b/src/Perpetuum/Zones/NpcSystem/Creature.cs
@@ -4,6 +4,7 @@
using Perpetuum.Units;
using Perpetuum.Zones.Effects;
using Perpetuum.Zones.Eggs;
+using Perpetuum.Zones.Intrusion;
using Perpetuum.Zones.LandMines;
using Perpetuum.Zones.Locking;
using Perpetuum.Zones.Locking.Locks;
@@ -16,7 +17,7 @@ public abstract class Creature : Robot
{
protected override void UpdateUnitVisibility(Unit target)
{
- if (target is AreaBomb || target is LandMine)
+ if (target is AreaBomb || target is LandMine || target is SAP)
{
UpdateVisibility(target);
}
diff --git a/src/Perpetuum/Zones/NpcSystem/Faction.cs b/src/Perpetuum/Zones/NpcSystem/Faction.cs
index 5c8a29e79..4b995f191 100644
--- a/src/Perpetuum/Zones/NpcSystem/Faction.cs
+++ b/src/Perpetuum/Zones/NpcSystem/Faction.cs
@@ -4,5 +4,6 @@ public enum Faction
{
Niani,
Syndicate,
+ Cultist,
}
}
diff --git a/src/Perpetuum/Zones/NpcSystem/INpcPresence.cs b/src/Perpetuum/Zones/NpcSystem/INpcPresence.cs
new file mode 100644
index 000000000..76a9eb253
--- /dev/null
+++ b/src/Perpetuum/Zones/NpcSystem/INpcPresence.cs
@@ -0,0 +1,26 @@
+using Perpetuum.Zones.NpcSystem.Presences;
+
+namespace Perpetuum.Zones.NpcSystem
+{
+ public interface INpcPresence
+ {
+ DynamicPresence ActivePresence { get; }
+
+ int PresenceId { get; }
+
+ bool Spawned { get; }
+
+ double Threshold { get; }
+
+ int MinStability { get; }
+
+ void SetActivePresence(DynamicPresence presence);
+
+ bool IsActivePresence(Presence presence);
+
+ ///
+ /// Deactivate ActivePresence
+ ///
+ void DeactivatePresence();
+ }
+}
\ No newline at end of file
diff --git a/src/Perpetuum/Zones/NpcSystem/INpcPresences.cs b/src/Perpetuum/Zones/NpcSystem/INpcPresences.cs
new file mode 100644
index 000000000..5be1a35d4
--- /dev/null
+++ b/src/Perpetuum/Zones/NpcSystem/INpcPresences.cs
@@ -0,0 +1,17 @@
+using Perpetuum.Zones.NpcSystem.Presences;
+
+namespace Perpetuum.Zones.NpcSystem
+{
+ public interface INpcPresences
+ {
+ INpcPresence GetNextPresence(double threshold);
+
+ INpcPresence GetNextPresence(int minStability);
+
+ bool HasActivePresence(Presence presence);
+
+ INpcPresence GetActivePresence(Presence presence);
+
+ INpcPresence[] GetAllActivePresences();
+ }
+}
diff --git a/src/Perpetuum/Zones/NpcSystem/Npc.cs b/src/Perpetuum/Zones/NpcSystem/Npc.cs
index 59388d7cc..81386f7d3 100644
--- a/src/Perpetuum/Zones/NpcSystem/Npc.cs
+++ b/src/Perpetuum/Zones/NpcSystem/Npc.cs
@@ -7,6 +7,7 @@
using Perpetuum.Services.MissionEngine.MissionTargets;
using Perpetuum.Units;
using Perpetuum.Zones.Eggs;
+using Perpetuum.Zones.Intrusion;
using Perpetuum.Zones.LandMines;
using Perpetuum.Zones.RemoteControl;
using System;
@@ -191,13 +192,20 @@ protected override bool IsHostileFor(Unit unit)
internal override bool IsHostile(Npc npc)
{
- return npc.ED.Options.Faction != ED.Options.Faction;
+ return (npc.ED.Options.Faction == Faction.Syndicate && npc.ED.Options.Faction != Faction.Syndicate) ||
+ (npc.ED.Options.Faction != Faction.Syndicate && npc.ED.Options.Faction == Faction.Syndicate);
+ }
+
+ internal override bool IsHostile(SAP sap)
+ {
+ return ED.Options.Faction == Faction.Cultist;
}
protected override void UpdateUnitVisibility(Unit target)
{
if (target is RemoteControlledCreature ||
target is LandMine ||
+ target is SAP ||
(target is Npc npc && npc.ED.Options.Faction != ED.Options.Faction))
{
UpdateVisibility(target);
diff --git a/src/Perpetuum/Zones/NpcSystem/Reinforcements/INpcReinforcementWave.cs b/src/Perpetuum/Zones/NpcSystem/Reinforcements/INpcReinforcementWave.cs
deleted file mode 100644
index 1240a87eb..000000000
--- a/src/Perpetuum/Zones/NpcSystem/Reinforcements/INpcReinforcementWave.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using Perpetuum.Zones.NpcSystem.Presences;
-
-namespace Perpetuum.Zones.NpcSystem.Reinforcements
-{
- ///
- /// Represents a single npc presence and its spawned state
- ///
- public interface INpcReinforcementWave
- {
- int PresenceId { get; }
- DynamicPresence ActivePresence { get; }
- double Threshold { get; }
- bool Spawned { get; }
-
- ///
- /// Set the ActivePresence and mark this wave as "Spawned"
- ///
- /// presence that is spawned to the zone
- void SetActivePresence(DynamicPresence presence);
-
- ///
- /// Test if the provided presence is the ActivePresence of this wave
- ///
- /// Presence to compare
- /// true if reference is equal
- bool IsActivePresence(Presence presence);
-
- ///
- /// Deactivate ActivePresence
- ///
- void DeactivatePresence();
- }
-}
diff --git a/src/Perpetuum/Zones/NpcSystem/Reinforcements/INpcReinforcements.cs b/src/Perpetuum/Zones/NpcSystem/Reinforcements/INpcReinforcements.cs
deleted file mode 100644
index 2985a94db..000000000
--- a/src/Perpetuum/Zones/NpcSystem/Reinforcements/INpcReinforcements.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using Perpetuum.Zones.NpcSystem.Presences;
-
-namespace Perpetuum.Zones.NpcSystem.Reinforcements
-{
- ///
- /// Ore NPC Spawn - a list of presences that spawn at particular percentages of some activity completion
- ///
- public interface INpcReinforcements
- {
- ///
- /// Gets the next IOreNpcData for the provided threshold percent mined
- ///
- /// double of range [0.-1.] representing a percentage
- /// IOreNpcData
- INpcReinforcementWave GetNextPresence(double threshold);
-
- ///
- /// Does this INpcReinforcements have the provided Presence active?
- ///
- /// Presence to compare
- /// true if provided presence is spawned in this INpcReinforcements
- bool HasActivePresence(Presence presence);
-
- ///
- /// Get the INpcReinforcementWave of some active Presence
- ///
- /// Presence to compare
- /// INpcReinforcementWave of spawned presence
- INpcReinforcementWave GetActiveWaveOfPresence(Presence presence);
-
- ///
- /// Get all active waves (waves with active presence)
- ///
- /// INpcReinforcementWaves with active presences
- INpcReinforcementWave[] GetAllActiveWaves();
- }
-}
diff --git a/src/Perpetuum/Zones/NpcSystem/Reinforcements/INpcReinforcementsRepository.cs b/src/Perpetuum/Zones/NpcSystem/Reinforcements/INpcReinforcementsRepository.cs
index 91c3b64dd..4c505345b 100644
--- a/src/Perpetuum/Zones/NpcSystem/Reinforcements/INpcReinforcementsRepository.cs
+++ b/src/Perpetuum/Zones/NpcSystem/Reinforcements/INpcReinforcementsRepository.cs
@@ -7,7 +7,7 @@ namespace Perpetuum.Zones.NpcSystem.Reinforcements
///
public interface INpcReinforcementsRepository
{
- INpcReinforcements CreateOreNPCSpawn(MaterialType materialType, int zoneId);
- INpcReinforcements CreateNpcBossAddSpawn(NpcBossInfo npcBossInfo, int zoneId);
+ INpcPresences CreateOreNPCSpawn(MaterialType materialType, int zoneId);
+ INpcPresences CreateNpcBossAddSpawn(NpcBossInfo npcBossInfo, int zoneId);
}
}
diff --git a/src/Perpetuum/Zones/NpcSystem/Reinforcements/NpcReinforcementWave.cs b/src/Perpetuum/Zones/NpcSystem/Reinforcements/NpcReinforcementWave.cs
index 52d53557b..e34d94656 100644
--- a/src/Perpetuum/Zones/NpcSystem/Reinforcements/NpcReinforcementWave.cs
+++ b/src/Perpetuum/Zones/NpcSystem/Reinforcements/NpcReinforcementWave.cs
@@ -1,14 +1,17 @@
using Perpetuum.Zones.NpcSystem.Presences;
+using System;
namespace Perpetuum.Zones.NpcSystem.Reinforcements
{
- public class NpcReinforcementWave : INpcReinforcementWave
+ public class NpcReinforcementWave : INpcPresence
{
public int PresenceId { get; }
public double Threshold { get; }
public bool Spawned { get; private set; }
public DynamicPresence ActivePresence { get; private set; }
+ public int MinStability => throw new NotImplementedException();
+
public NpcReinforcementWave(int presenceID, double threshold)
{
PresenceId = presenceID;
diff --git a/src/Perpetuum/Zones/NpcSystem/Reinforcements/NpcReinforcements.cs b/src/Perpetuum/Zones/NpcSystem/Reinforcements/NpcReinforcements.cs
index 87f4e19e4..7086c7510 100644
--- a/src/Perpetuum/Zones/NpcSystem/Reinforcements/NpcReinforcements.cs
+++ b/src/Perpetuum/Zones/NpcSystem/Reinforcements/NpcReinforcements.cs
@@ -5,14 +5,14 @@
namespace Perpetuum.Zones.NpcSystem.Reinforcements
{
- public class NpcReinforcements : INpcReinforcements
+ public class NpcReinforcements : INpcPresences
{
private const double ThresholdDelta = 0.1;
// Sorted array of OreNpcData by threshold
- private readonly INpcReinforcementWave[] _presences;
+ private readonly INpcPresence[] _presences;
- public NpcReinforcements(INpcReinforcementWave[] presences)
+ public NpcReinforcements(INpcPresence[] presences)
{
_presences = presences.OrderBy(s => Array.IndexOf(presences, s.Threshold)).ToArray();
}
@@ -22,7 +22,7 @@ public NpcReinforcements(INpcReinforcementWave[] presences)
///
/// percentage expressed as [0.0-1.0]
/// INpcReinforcementWave or null
- public INpcReinforcementWave GetNextPresence(double threshold)
+ public INpcPresence GetNextPresence(double threshold)
{
for (int i = _presences.Length - 1; i >= 0; i--)
{
@@ -39,12 +39,12 @@ public bool HasActivePresence(Presence presence)
return _presences.Any(w => w.IsActivePresence(presence));
}
- public INpcReinforcementWave GetActiveWaveOfPresence(Presence presence)
+ public INpcPresence GetActivePresence(Presence presence)
{
return _presences.Single(w => w.IsActivePresence(presence));
}
- public INpcReinforcementWave[] GetAllActiveWaves()
+ public INpcPresence[] GetAllActivePresences()
{
return _presences.Where(w => !w.IsActivePresence(null)).ToArray();
}
@@ -60,5 +60,10 @@ public override string ToString()
sb.AppendLine("}");
return sb.ToString();
}
+
+ public INpcPresence GetNextPresence(int minStability)
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/src/Perpetuum/Zones/NpcSystem/Reinforcements/NpcReinforcementsRepository.cs b/src/Perpetuum/Zones/NpcSystem/Reinforcements/NpcReinforcementsRepository.cs
index 559532600..2ee6fc146 100644
--- a/src/Perpetuum/Zones/NpcSystem/Reinforcements/NpcReinforcementsRepository.cs
+++ b/src/Perpetuum/Zones/NpcSystem/Reinforcements/NpcReinforcementsRepository.cs
@@ -9,33 +9,40 @@ public class NpcReinforcementsRepository : INpcReinforcementsRepository
{
private const string queryStr = "SELECT threshold, presenceId from npcreinforcements WHERE targetId=@target AND reinforcementType=@type AND (zoneId IS NULL OR zoneId=@zone);";
- public INpcReinforcements CreateOreNPCSpawn(MaterialType materialType, int zoneId)
+ public INpcPresences CreateOreNPCSpawn(MaterialType materialType, int zoneId)
{
- var records = Db.Query().CommandText(queryStr)
+ INpcPresence[] records = Db.Query()
+ .CommandText(queryStr)
.SetParameter("@target", materialType)
.SetParameter("@type", ReinforcementType.Minerals)
.SetParameter("@zone", zoneId)
.Execute()
- .Select(CreateFromRecord).ToArray();
+ .Select(CreateFromRecord)
+ .ToArray();
+
return new NpcReinforcements(records);
}
- private static INpcReinforcementWave CreateFromRecord(IDataRecord record)
+ private static INpcPresence CreateFromRecord(IDataRecord record)
{
- var presence = record.GetValue("presenceId");
- var threshold = record.GetValue("threshold");
- var pair = new NpcReinforcementWave(presence, threshold);
+ int presence = record.GetValue("presenceId");
+ double threshold = record.GetValue("threshold");
+ NpcReinforcementWave pair = new NpcReinforcementWave(presence, threshold);
+
return pair;
}
- public INpcReinforcements CreateNpcBossAddSpawn(NpcBossInfo npcBossInfo, int zoneId)
+ public INpcPresences CreateNpcBossAddSpawn(NpcBossInfo npcBossInfo, int zoneId)
{
- var records = Db.Query().CommandText(queryStr)
+ INpcPresence[] records = Db.Query()
+ .CommandText(queryStr)
.SetParameter("@target", npcBossInfo.FlockId)
.SetParameter("@type", ReinforcementType.Boss)
.SetParameter("@zone", zoneId)
.Execute()
- .Select(CreateFromRecord).ToArray();
+ .Select(CreateFromRecord)
+ .ToArray();
+
return new NpcReinforcements(records);
}
}
diff --git a/src/Perpetuum/Zones/NpcSystem/SapAttackers/ISapAttackersRepository.cs b/src/Perpetuum/Zones/NpcSystem/SapAttackers/ISapAttackersRepository.cs
new file mode 100644
index 000000000..3d711166e
--- /dev/null
+++ b/src/Perpetuum/Zones/NpcSystem/SapAttackers/ISapAttackersRepository.cs
@@ -0,0 +1,7 @@
+namespace Perpetuum.Zones.NpcSystem.SapAttackers
+{
+ public interface ISapAttackersRepository
+ {
+ INpcPresences CreateSapAttackersSpawn(int sapDefinition, int zoneId);
+ }
+}
diff --git a/src/Perpetuum/Zones/NpcSystem/SapAttackers/SapAttackerPresence.cs b/src/Perpetuum/Zones/NpcSystem/SapAttackers/SapAttackerPresence.cs
new file mode 100644
index 000000000..ad7862a1c
--- /dev/null
+++ b/src/Perpetuum/Zones/NpcSystem/SapAttackers/SapAttackerPresence.cs
@@ -0,0 +1,42 @@
+using Perpetuum.Zones.NpcSystem.Presences;
+using System;
+
+namespace Perpetuum.Zones.NpcSystem.SapAttackers
+{
+ public class SapAttackerPresence : INpcPresence
+ {
+ public int PresenceId { get; }
+ public int MinStability { get; }
+ public bool Spawned { get; private set; }
+ public DynamicPresence ActivePresence { get; private set; }
+
+ public double Threshold => throw new NotImplementedException();
+
+ public SapAttackerPresence(int presenceID, int stability)
+ {
+ PresenceId = presenceID;
+ MinStability = stability;
+ }
+
+ public override string ToString()
+ {
+ return $"{MinStability}:{PresenceId} Spawned? {Spawned}";
+ }
+
+ public void SetActivePresence(DynamicPresence presence)
+ {
+ ActivePresence = presence;
+ Spawned = true;
+ }
+
+ public bool IsActivePresence(Presence presence)
+ {
+ return ReferenceEquals(ActivePresence, presence);
+ }
+
+ public void DeactivatePresence()
+ {
+ ActivePresence = null;
+ }
+ }
+}
diff --git a/src/Perpetuum/Zones/NpcSystem/SapAttackers/SapAttackers.cs b/src/Perpetuum/Zones/NpcSystem/SapAttackers/SapAttackers.cs
new file mode 100644
index 000000000..339807f58
--- /dev/null
+++ b/src/Perpetuum/Zones/NpcSystem/SapAttackers/SapAttackers.cs
@@ -0,0 +1,62 @@
+using Perpetuum.Zones.NpcSystem.Presences;
+using System;
+using System.Linq;
+using System.Text;
+
+namespace Perpetuum.Zones.NpcSystem.SapAttackers
+{
+ public class SapAttackers : INpcPresences
+ {
+ private readonly INpcPresence[] _presences;
+
+ public SapAttackers(INpcPresence[] presences)
+ {
+ _presences = presences.OrderBy(s => Array.IndexOf(presences, s.MinStability)).ToArray();
+ }
+
+ public INpcPresence GetNextPresence(int stability)
+ {
+ for (int i = _presences.Length - 1; i >= 0; i--)
+ {
+ if (stability - _presences[i].MinStability < stability)
+ {
+ return _presences[i].Spawned ? null : _presences[i];
+ }
+ }
+ return null;
+ }
+
+ public bool HasActivePresence(Presence presence)
+ {
+ return _presences.Any(w => w.IsActivePresence(presence));
+ }
+
+ public INpcPresence GetActivePresence(Presence presence)
+ {
+ return _presences.Single(w => w.IsActivePresence(presence));
+ }
+
+ public INpcPresence[] GetAllActivePresences()
+ {
+ return _presences.Where(w => !w.IsActivePresence(null)).ToArray();
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendLine("SapAttackerSpawn {");
+ for (int i = 0; i < _presences.Length; i++)
+ {
+ sb.AppendLine(_presences[i].ToString());
+ }
+ sb.AppendLine("}");
+
+ return sb.ToString();
+ }
+
+ public INpcPresence GetNextPresence(double threshold)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Perpetuum/Zones/NpcSystem/SapAttackers/SapAttackersRepository.cs b/src/Perpetuum/Zones/NpcSystem/SapAttackers/SapAttackersRepository.cs
new file mode 100644
index 000000000..553145d8e
--- /dev/null
+++ b/src/Perpetuum/Zones/NpcSystem/SapAttackers/SapAttackersRepository.cs
@@ -0,0 +1,33 @@
+using Perpetuum.Data;
+using System.Data;
+using System.Linq;
+
+namespace Perpetuum.Zones.NpcSystem.SapAttackers
+{
+ public class SapAttackersRepository : ISapAttackersRepository
+ {
+ private const string queryStr = "SELECT MinStability, PresenceId from SapAttackers WHERE SapDefinition=@sapDefinition AND (zoneId IS NULL OR zoneId=@zone);";
+
+ public INpcPresences CreateSapAttackersSpawn(int sapDefinition, int zoneId)
+ {
+ INpcPresence[] records = Db.Query()
+ .CommandText(queryStr)
+ .SetParameter("@sapDefinition", sapDefinition)
+ .SetParameter("@zone", zoneId)
+ .Execute()
+ .Select(CreateFromRecord)
+ .ToArray();
+
+ return new SapAttackers(records);
+ }
+
+ private static INpcPresence CreateFromRecord(IDataRecord record)
+ {
+ int presence = record.GetValue("PresenceId");
+ int minStability = record.GetValue("MinStability");
+ SapAttackerPresence pair = new SapAttackerPresence(presence, minStability);
+
+ return pair;
+ }
+ }
+}
diff --git a/src/Perpetuum/app.config b/src/Perpetuum/app.config
new file mode 100644
index 000000000..a2fe38b09
--- /dev/null
+++ b/src/Perpetuum/app.config
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Perpetuum/packages.config b/src/Perpetuum/packages.config
index 5f43db920..bd32f549f 100644
--- a/src/Perpetuum/packages.config
+++ b/src/Perpetuum/packages.config
@@ -1,11 +1,27 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
-
-
-
+
+
+
+
+
\ No newline at end of file