diff --git a/DS3ConnectionInfo/App.config b/DS3ConnectionInfo/App.config
index 362897a..ec5eee0 100644
--- a/DS3ConnectionInfo/App.config
+++ b/DS3ConnectionInfo/App.config
@@ -133,6 +133,12 @@
+
+ 250
+
+
+ False
+
diff --git a/DS3ConnectionInfo/DS3Interop.cs b/DS3ConnectionInfo/DS3Interop.cs
index 2dfe7a4..35e4d43 100644
--- a/DS3ConnectionInfo/DS3Interop.cs
+++ b/DS3ConnectionInfo/DS3Interop.cs
@@ -3,6 +3,7 @@
using System.Diagnostics;
using System.Globalization;
using System.Linq;
+using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using DS3ConnectionInfo.WinAPI;
@@ -35,20 +36,96 @@ public enum NetStatus
}
///
- /// BaseB (WorldChrMan) address
+ /// Ways of joining a DS3 online session.
///
- public const long BaseB = 0x144768E78;
+ public enum JoinMethod
+ {
+ None,
+ Arena,
+ Convenant,
+ RedEyeOrb,
+ WhiteSign,
+ RedSign
+ }
+
+ private static readonly JoinMethod[] invTypeToJoinMethod = new JoinMethod[22]
+ {
+ JoinMethod.None,
+ JoinMethod.WhiteSign,
+ JoinMethod.RedSign,
+ JoinMethod.RedEyeOrb,
+ JoinMethod.WhiteSign,
+ JoinMethod.None, // 5 Missing from TGA list
+ JoinMethod.Convenant,
+ JoinMethod.Convenant,
+ JoinMethod.None, // (Guardian of Rosaria)
+ JoinMethod.Convenant,
+ JoinMethod.Convenant,
+ JoinMethod.None, // (Avatar)
+ JoinMethod.Arena,
+ JoinMethod.None, // (Umbasa White)
+ JoinMethod.WhiteSign,
+ JoinMethod.RedSign,
+ JoinMethod.RedSign,
+ JoinMethod.RedEyeOrb,
+ JoinMethod.RedEyeOrb,
+ JoinMethod.None, // (Force Join Session)
+ JoinMethod.None, // (Red Hunter)
+ JoinMethod.Convenant
+ };
+
+ public struct SpEffect
+ {
+ public int id;
+ public float durationLeft;
+ public float duration;
+ public float interval;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ private struct SpEffectInternal
+ {
+ [FieldOffset(0x00)]
+ public float durationLeft;
+ [FieldOffset(0x04)]
+ public float duration;
+ [FieldOffset(0x08)]
+ public float interval;
+ [FieldOffset(0x60)]
+ public int id;
+ [FieldOffset(0x78)]
+ public long ptrNext;
+ public SpEffect ToSpEffect()
+ {
+ return new SpEffect { id = id, duration = duration, durationLeft = durationLeft, interval = interval };
+ }
+ }
///
- /// SprjSessionManager address
+ /// BaseA (Game) address
///
- public const long SprjSession = 0x144780990;
+ public const long BaseA = 0x144740178;
+
+ ///
+ /// BaseB (WorldChrMan) address
+ ///
+ public const long BaseB = 0x144768E78;
///
/// BaseC (GameOptionMan) address
///
public const long BaseC = 0x144743AB0;
+ ///
+ /// FRPGNet address
+ ///
+ public const long BaseE = 0x14473FD08;
+
+ ///
+ /// SprjSessionManager address
+ ///
+ public const long SprjSession = 0x144780990;
+
///
/// DS3.exe Base Address
///
@@ -127,8 +204,6 @@ public static bool TryAttach()
if (pArr.Length == 0) return false;
Process = pArr[0];
- for (int i = 1; i < pArr.Length; i++) pArr[i].Dispose();
-
ProcHandle = Kernel32.OpenProcess(ProcessAccessFlags.AllAccess, false, Process.Id);
if (ProcHandle == IntPtr.Zero) Detach();
return ProcHandle != IntPtr.Zero;
@@ -212,5 +287,33 @@ public static bool IsMyWorld()
{
return MemoryManager.ReadGenericPtr(ProcHandle, BaseC, 0xB1E) == 1;
}
+
+ public static IEnumerable ActiveSpEffects()
+ {
+ long addrNext = MemoryManager.ReadGenericPtr(ProcHandle, BaseA, 0x10, 0x920, 0x8);
+
+ while (addrNext != 0)
+ {
+ SpEffectInternal fx = MemoryManager.ReadGeneric(ProcHandle, addrNext);
+ addrNext = fx.ptrNext;
+ yield return fx.ToSpEffect();
+ }
+ }
+
+ public static bool IsSearchingInvasion()
+ {
+ foreach (SpEffect fx in ActiveSpEffects())
+ {
+ if (fx.id == 9200) return true;
+ }
+ return false;
+ }
+
+ public static JoinMethod GetJoinMethod()
+ {
+ int invType = MemoryManager.ReadGenericPtr(ProcHandle, BaseC, 0xC54);
+ if (invType > 0 || invType < -21) return JoinMethod.None;
+ else return invTypeToJoinMethod[-invType];
+ }
}
}
diff --git a/DS3ConnectionInfo/MainWindow.xaml b/DS3ConnectionInfo/MainWindow.xaml
index 1af5a9f..5322d38 100644
--- a/DS3ConnectionInfo/MainWindow.xaml
+++ b/DS3ConnectionInfo/MainWindow.xaml
@@ -23,7 +23,14 @@
-
+
+
+
+
+
+
+
+
@@ -89,8 +96,8 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
@@ -148,16 +160,21 @@
-
+
+
- Show/Hide Session Info Columns:
-
+
+
+
+ Show/Hide Session Info Columns:
+
Slot
Char. Name
Team
@@ -170,11 +187,11 @@
Late Packet %
Location
-
-
+
+
DESC
-
+
diff --git a/DS3ConnectionInfo/MainWindow.xaml.cs b/DS3ConnectionInfo/MainWindow.xaml.cs
index 2b12bba..8f886c7 100644
--- a/DS3ConnectionInfo/MainWindow.xaml.cs
+++ b/DS3ConnectionInfo/MainWindow.xaml.cs
@@ -31,8 +31,10 @@ public partial class MainWindow
private ObservableCollection playerData;
private OverlayWindow overlay;
- private int activeFilterEffect = 0;
+ private bool reoSpamming = false;
private int reoSpamCnt = 0;
+ private bool pingCheked = false;
+ private bool hadInvaded = false;
public MainWindow()
{
@@ -119,69 +121,81 @@ private void UpdateTimer_Tick(object sender, EventArgs e)
// Queue position update after the overlay has re-rendered
Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, new Action(overlay.UpdatePosition));
+ DS3Interop.NetStatus status = DS3Interop.GetNetworkState();
+ if (reoSpamming && !Settings.Default.SpamRedEyeOrb)
+ {
+ reoSpamming = false;
+ reoSpamCnt = 0;
+ }
+ if (status == DS3Interop.NetStatus.None)
+ {
+ if (hadInvaded && !reoSpamming) DS3Interop.ApplyEffect(11);
+ if (reoSpamming)
+ {
+ reoSpamCnt = (reoSpamCnt + 1) % 5;
+ if (DS3Interop.IsSearchingInvasion() ^ (reoSpamCnt != 0)) DS3Interop.ApplyEffect(11);
+ }
+ hadInvaded = false;
+ pingCheked = false;
+ }
if (Settings.Default.UsePingFilter)
{
- DS3Interop.NetStatus status = DS3Interop.GetNetworkState();
if (status == DS3Interop.NetStatus.Host || status == DS3Interop.NetStatus.TryCreateSession || DS3Interop.InLoadingScreen())
- { // Someone invaded, or the local player summoned a phantom
+ { // Someone invaded, or the local player summoned a phantom, or ping filter was too late
pingFilterTimer.Stop();
- activeFilterEffect = 0;
- }
-
- if (status == DS3Interop.NetStatus.None && activeFilterEffect == 11)
- { // Basically resetting REO
- if (reoSpamCnt >= 3)
- {
- DS3Interop.ApplyEffect(11);
- }
- reoSpamCnt = (reoSpamCnt + 1) % 5;
+ reoSpamming = false;
+ reoSpamCnt = 0;
+ pingCheked = false;
}
-
- if (activeFilterEffect != 0 && status == DS3Interop.NetStatus.Client && !pingFilterTimer.IsEnabled)
+ if (status == DS3Interop.NetStatus.Client && !pingFilterTimer.IsEnabled && !pingCheked)
{ // Connection has been established
+ pingCheked = true;
pingFilterTimer.Interval = TimeSpan.FromSeconds(Settings.Default.SamplingDelay);
pingFilterTimer.Start();
}
}
- else
- {
- activeFilterEffect = 0;
- pingFilterTimer.Stop();
- }
+ else pingFilterTimer.Stop();
}
private void PingFilterTimer_Tick(object sender, EventArgs e)
{
double sumPing = 0; int n = 0;
+ bool absPingRespected = true;
foreach (Player p in Player.ActivePlayers())
{
if (p.Ping != -1)
{
+ absPingRespected &= p.Ping < Settings.Default.MaxAbsPing;
sumPing += p.Ping;
n++;
}
}
if (n == 0)
- { // Wait until one player has a ping
+ { // Wait until at least one player has a ping
pingFilterTimer.Interval = TimeSpan.FromSeconds(0.5);
return;
}
- if (sumPing / n > Settings.Default.MaxAvgPing)
+ if ((!absPingRespected || sumPing / n > Settings.Default.MaxAvgPing) && !DS3Interop.InLoadingScreen())
{
+ var joinMethod = DS3Interop.GetJoinMethod();
DS3Interop.LeaveSession();
- if (activeFilterEffect != 11) DS3Interop.ApplyEffect(activeFilterEffect);
- else reoSpamCnt = 4;
+ if (joinMethod == DS3Interop.JoinMethod.RedEyeOrb)
+ hadInvaded = true;
+ else if (joinMethod == DS3Interop.JoinMethod.RedSign)
+ DS3Interop.ApplyEffect(10);
+ else if (joinMethod == DS3Interop.JoinMethod.WhiteSign)
+ DS3Interop.ApplyEffect(4);
}
- else activeFilterEffect = 0;
+ else reoSpamming = false;
pingFilterTimer.Stop();
}
private void MainWindow_Closed(object sender, EventArgs e)
{
+ Settings.Default.Save();
overlay.Close();
HotkeyManager.Disable();
ETWPingMonitor.Stop();
- Settings.Default.Save();
}
private void GameStartTimer_Tick(object sender, EventArgs e)
@@ -213,9 +227,9 @@ private void GameStartTimer_Tick(object sender, EventArgs e)
HotkeyManager.AddHotkey(DS3Interop.WinHandle, () => Settings.Default.BorderlessHotkey, () => swBorderless.IsOn ^= true);
HotkeyManager.AddHotkey(DS3Interop.WinHandle, () => Settings.Default.OverlayHotkey, () => swOverlay.IsOn ^= true);
HotkeyManager.AddHotkey(DS3Interop.WinHandle, () => Settings.Default.PingFilterHotkey, () => Settings.Default.UsePingFilter ^= true);
- HotkeyManager.AddHotkey(DS3Interop.WinHandle, () => Settings.Default.REOHotkey, () => PingFilterAction(11));
- HotkeyManager.AddHotkey(DS3Interop.WinHandle, () => Settings.Default.RSDHotkey, () => PingFilterAction(10));
- HotkeyManager.AddHotkey(DS3Interop.WinHandle, () => Settings.Default.WSDHotkey, () => PingFilterAction(4));
+ HotkeyManager.AddHotkey(DS3Interop.WinHandle, () => Settings.Default.REOHotkey, () => OnlineHotkey(11));
+ HotkeyManager.AddHotkey(DS3Interop.WinHandle, () => Settings.Default.RSDHotkey, () => OnlineHotkey(10));
+ HotkeyManager.AddHotkey(DS3Interop.WinHandle, () => Settings.Default.WSDHotkey, () => OnlineHotkey(4));
HotkeyManager.AddHotkey(DS3Interop.WinHandle, () => Settings.Default.LeaveSessionHotkey, () => DS3Interop.LeaveSession());
ETWPingMonitor.Start();
@@ -224,14 +238,15 @@ private void GameStartTimer_Tick(object sender, EventArgs e)
}
}
- private void PingFilterAction(int effect)
+ private void OnlineHotkey(int effect)
{
- if (Settings.Default.UsePingFilter && !DS3Interop.InLoadingScreen())
+ if (DS3Interop.InLoadingScreen()) return;
+ if (effect == 11 && Settings.Default.SpamRedEyeOrb)
{
- pingFilterTimer.Stop();
- activeFilterEffect = (effect == activeFilterEffect) ? 0 : effect;
- if (activeFilterEffect != 11 || reoSpamCnt != 4) DS3Interop.ApplyEffect(effect);
+ reoSpamming ^= true;
reoSpamCnt = 0;
+ if (!reoSpamming && DS3Interop.IsSearchingInvasion())
+ DS3Interop.ApplyEffect(11);
}
else DS3Interop.ApplyEffect(effect);
}
diff --git a/DS3ConnectionInfo/OverlayWindow.xaml b/DS3ConnectionInfo/OverlayWindow.xaml
index 156e169..616e415 100644
--- a/DS3ConnectionInfo/OverlayWindow.xaml
+++ b/DS3ConnectionInfo/OverlayWindow.xaml
@@ -32,7 +32,14 @@
-
+
+
+
+
+
+
+
+
diff --git a/DS3ConnectionInfo/Settings.Designer.cs b/DS3ConnectionInfo/Settings.Designer.cs
index 5aea7e4..c4191fd 100644
--- a/DS3ConnectionInfo/Settings.Designer.cs
+++ b/DS3ConnectionInfo/Settings.Designer.cs
@@ -430,5 +430,29 @@ public int PingFilterHotkey {
this["OverlayColVisibility"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("250")]
+ public double MaxAbsPing {
+ get {
+ return ((double)(this["MaxAbsPing"]));
+ }
+ set {
+ this["MaxAbsPing"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool SpamRedEyeOrb {
+ get {
+ return ((bool)(this["SpamRedEyeOrb"]));
+ }
+ set {
+ this["SpamRedEyeOrb"] = value;
+ }
+ }
}
}
diff --git a/DS3ConnectionInfo/Settings.settings b/DS3ConnectionInfo/Settings.settings
index 8e7a905..c6b9336 100644
--- a/DS3ConnectionInfo/Settings.settings
+++ b/DS3ConnectionInfo/Settings.settings
@@ -134,5 +134,11 @@
<string>Hidden</string>
</ArrayOfString>
+
+ 250
+
+
+ False
+
\ No newline at end of file
diff --git a/DS3ConnectionInfo/VersionCheck.cs b/DS3ConnectionInfo/VersionCheck.cs
index cb3d46b..4e54cfc 100644
--- a/DS3ConnectionInfo/VersionCheck.cs
+++ b/DS3ConnectionInfo/VersionCheck.cs
@@ -14,7 +14,7 @@ namespace DS3ConnectionInfo
{
static class VersionCheck
{
- public static readonly string CurrentVersion = "V4";
+ public static readonly string CurrentVersion = "V4.1";
public static JObject LatestRelease { get; private set; }
public static bool FetchLatest()