mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-07-15 15:19:57 +00:00
Update GWCA (#1484)
* Improve GWCA bindings generator based on headers * Move all structs to gwca * Progress * Complete parser work * More generator adjustments * GWCA fixes * GWCA improvements * GWCA fixes * GWCA fixes * GWCA fixes * GWCA fixes * Fix API usage of GWCA * Update GWCA --------- Co-authored-by: Alexandru Macocian <amacocian@microsoft.com>
This commit is contained in:
@@ -1,19 +0,0 @@
|
||||
using Daybreak.API.Interop;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Daybreak.API.Converters;
|
||||
|
||||
public sealed class PointerValueConverter : JsonConverter<PointerValue>
|
||||
{
|
||||
public override PointerValue Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
var s = reader.GetString() ?? throw new JsonException("Expected string");
|
||||
return PointerValue.Parse(s);
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, PointerValue value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStringValue(value.ToString());
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
using Daybreak.API.Interop.GuildWars;
|
||||
using Daybreak.Shared.Models.Api;
|
||||
using ZLinq;
|
||||
|
||||
namespace Daybreak.API.Extensions;
|
||||
|
||||
public static class AttributeContextExtensions
|
||||
{
|
||||
public static List<AttributeEntry> GetAttributeEntryList(this AttributeContext[] attributes)
|
||||
public static IEnumerable<AttributeEntry> GetAttributeEntryList(this AttributeStructArray54 attributes)
|
||||
{
|
||||
return attributes
|
||||
.AsValueEnumerable()
|
||||
.Take(45) // There are only 45 maximum attributes in game
|
||||
.Where(a => a.LevelBase > 0 && a.Level >= a.LevelBase) // Select only attributes with points in them
|
||||
.Select(a => new AttributeEntry(a.Id, a.LevelBase, a.Level)).ToList();
|
||||
foreach (var attribute in attributes)
|
||||
{
|
||||
if (attribute.LevelBase > 0 && attribute.Level >= attribute.LevelBase)
|
||||
{
|
||||
yield return new AttributeEntry((uint)attribute.Id, attribute.LevelBase, attribute.Level);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
using Daybreak.API.Interop.GuildWars;
|
||||
|
||||
namespace Daybreak.API.Extensions;
|
||||
|
||||
public static class CharacterInformationExtensions
|
||||
{
|
||||
public unsafe static Profession GetPrimaryProfession(this CharacterInformation characterInformation)
|
||||
{
|
||||
return (Profession)((characterInformation.Props[2] >> 20) & 0xF);
|
||||
}
|
||||
|
||||
public unsafe static Profession GetSecondaryProfession(this CharacterInformation characterInformation)
|
||||
{
|
||||
return (Profession)((characterInformation.Props[7] >> 10) & 0xF);
|
||||
}
|
||||
|
||||
public unsafe static uint GetLevel(this CharacterInformation characterInformation)
|
||||
{
|
||||
return (characterInformation.Props[7] >> 4) & 0x3F;
|
||||
}
|
||||
|
||||
public unsafe static Campaign GetCampaign(this CharacterInformation characterInformation)
|
||||
{
|
||||
return (Campaign)(characterInformation.Props[7] & 0xF);
|
||||
}
|
||||
|
||||
public unsafe static MapID GetMapId(this CharacterInformation characterInformation)
|
||||
{
|
||||
return (MapID)((characterInformation.Props[0] >> 16) & 0xFFFF);
|
||||
}
|
||||
|
||||
public unsafe static bool IsPvP(this CharacterInformation characterInformation)
|
||||
{
|
||||
return ((characterInformation.Props[7] >> 9) & 0x1) == 0x1;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Daybreak.API.Interop.GuildWars;
|
||||
using Daybreak.API.Interop;
|
||||
using Daybreak.API.Interop.GuildWars;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Daybreak.API.Extensions;
|
||||
@@ -11,21 +12,21 @@ public static unsafe class GameContextExtensions
|
||||
{
|
||||
playerId = 0;
|
||||
if (gameContext.IsNull ||
|
||||
gameContext.Pointer->WorldContext is null ||
|
||||
gameContext.Pointer->WorldContext->PlayerControlledChar is null)
|
||||
gameContext.Pointer->World is null ||
|
||||
gameContext.Pointer->World->PlayerControlledChar is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
playerId = gameContext.Pointer->WorldContext->PlayerControlledChar->AgentId;
|
||||
playerId = gameContext.Pointer->World->PlayerControlledChar->AgentId;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryGetBuildContext(
|
||||
this WrappedPointer<GameContext> gameContext,
|
||||
[NotNullWhen(true)] out GuildWarsArray<SkillbarContext>? skillbars,
|
||||
[NotNullWhen(true)] out GuildWarsArray<SkillbarData>? skillbars,
|
||||
[NotNullWhen(true)] out GuildWarsArray<PartyAttribute>? attributes,
|
||||
[NotNullWhen(true)] out GuildWarsArray<ProfessionsContext>? professions,
|
||||
[NotNullWhen(true)] out GuildWarsArray<ProfessionState>? professions,
|
||||
[NotNullWhen(true)] out GuildWarsArray<uint>? unlockedSkills)
|
||||
{
|
||||
skillbars = default;
|
||||
@@ -33,15 +34,15 @@ public static unsafe class GameContextExtensions
|
||||
professions = default;
|
||||
unlockedSkills = default;
|
||||
if (gameContext.IsNull ||
|
||||
gameContext.Pointer->WorldContext is null)
|
||||
gameContext.Pointer->World is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
skillbars = gameContext.Pointer->WorldContext->Skillbars;
|
||||
attributes = gameContext.Pointer->WorldContext->Attributes;
|
||||
professions = gameContext.Pointer->WorldContext->Professions;
|
||||
unlockedSkills = gameContext.Pointer->WorldContext->UnlockedCharacterSkills;
|
||||
skillbars = gameContext.Pointer->World->Skillbar.Value;
|
||||
attributes = gameContext.Pointer->World->Attributes.Value;
|
||||
professions = gameContext.Pointer->World->PartyProfessionStates;
|
||||
unlockedSkills = gameContext.Pointer->World->UnlockedCharacterSkills;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -57,15 +58,16 @@ public static unsafe class GameContextExtensions
|
||||
heroes = default;
|
||||
henchmen = default;
|
||||
if (gameContext.IsNull ||
|
||||
gameContext.Pointer->PartyContext is null)
|
||||
gameContext.Pointer->Party is 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
partyId = gameContext.Pointer->PartyContext->PlayerParty->PartyId;
|
||||
players = gameContext.Pointer->PartyContext->PlayerParty->Players;
|
||||
heroes = gameContext.Pointer->PartyContext->PlayerParty->Heroes;
|
||||
henchmen = gameContext.Pointer->PartyContext->PlayerParty->Henchmen;
|
||||
var partyInfo = GWCA.GW.PartyMgr.GetPartyInfo(0);
|
||||
partyId = partyInfo->PartyId;
|
||||
players = partyInfo->Players;
|
||||
heroes = partyInfo->Heroes;
|
||||
henchmen = partyInfo->Henchmen;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -75,27 +77,27 @@ public static unsafe class GameContextExtensions
|
||||
{
|
||||
heroFlags = default;
|
||||
if (gameContext.IsNull ||
|
||||
gameContext.Pointer->WorldContext is null)
|
||||
gameContext.Pointer->World is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
heroFlags = gameContext.Pointer->WorldContext->HeroFlags;
|
||||
heroFlags = gameContext.Pointer->World->HeroFlags.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryGetAccountContext(
|
||||
this WrappedPointer<GameContext> gameContext,
|
||||
out WrappedPointer<AccountGameContext> accountContext)
|
||||
out WrappedPointer<AccountContext> accountContext)
|
||||
{
|
||||
accountContext = default;
|
||||
if (gameContext.IsNull ||
|
||||
gameContext.Pointer->AccountContext is null)
|
||||
gameContext.Pointer->Account is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
accountContext = gameContext.Pointer->AccountContext;
|
||||
accountContext = gameContext.Pointer->Account;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using Daybreak.API.Interop.GuildWars;
|
||||
|
||||
namespace Daybreak.API.Extensions;
|
||||
|
||||
public static class TitleExtensions
|
||||
{
|
||||
public static bool IsPercentageBased(this Title title)
|
||||
{
|
||||
return (title.Props & 1) != 0;
|
||||
}
|
||||
|
||||
public static bool HasTiers(this Title title)
|
||||
{
|
||||
return (title.Props & 3) == 2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x1AC)]
|
||||
[GWCAEquivalent("Frame")]
|
||||
public readonly struct Frame
|
||||
{
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly uint FrameLayout;
|
||||
|
||||
[FieldOffset(0x0018)]
|
||||
public readonly uint VisibilityFlags;
|
||||
|
||||
[FieldOffset(0x0020)]
|
||||
public readonly uint Type;
|
||||
|
||||
[FieldOffset(0x0024)]
|
||||
public readonly uint TemplateType;
|
||||
|
||||
[FieldOffset(0x00b8)]
|
||||
public readonly uint ChildOffsetId;
|
||||
|
||||
[FieldOffset(0x00bc)]
|
||||
public readonly uint FrameId;
|
||||
|
||||
[FieldOffset(0x018C)]
|
||||
public readonly uint FrameState;
|
||||
|
||||
public bool IsCreated => (this.FrameState & 0x4) != 0;
|
||||
public bool IsHidden => (this.FrameState & 0x200) != 0;
|
||||
public bool IsVisible => !this.IsHidden;
|
||||
public bool IsDIsabled => (this.FrameState & 0x10) != 0;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using System.Core.Extensions;
|
||||
|
||||
namespace Daybreak.API.Interop;
|
||||
|
||||
public sealed class GWAddressCache(Func<nuint> provider)
|
||||
{
|
||||
private readonly Func<nuint> provider = provider.ThrowIfNull();
|
||||
private nuint? cachedAddress;
|
||||
|
||||
public nuint? GetAddress()
|
||||
{
|
||||
if (this.cachedAddress.HasValue)
|
||||
{
|
||||
return this.cachedAddress.Value;
|
||||
}
|
||||
|
||||
var addr = this.provider();
|
||||
if (addr is 0x0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
this.cachedAddress = addr;
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
+16892
-692
File diff suppressed because it is too large
Load Diff
@@ -1,19 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop;
|
||||
|
||||
public sealed class GWDelegateCache<TDelegate>(GWAddressCache cache)
|
||||
where TDelegate : Delegate
|
||||
{
|
||||
public GWAddressCache Cache { get; } = cache;
|
||||
|
||||
public TDelegate? GetDelegate()
|
||||
{
|
||||
if (this.Cache.GetAddress() is not nuint address)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return Marshal.GetDelegateForFunctionPointer<TDelegate>((nint)address);
|
||||
}
|
||||
}
|
||||
@@ -1,312 +0,0 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop;
|
||||
|
||||
public abstract class GWFastCall(GWAddressCache target)
|
||||
{
|
||||
public readonly struct Void { }
|
||||
|
||||
public GWAddressCache Cache { get; } = target;
|
||||
public abstract void Initialize();
|
||||
|
||||
/// <summary>
|
||||
/// Builds a thunk for __fastcall with 1 parameter (ECX only).
|
||||
/// </summary>
|
||||
protected unsafe static nint BuildFastCallThunk1(nuint target)
|
||||
{
|
||||
if (target is 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var code = stackalloc byte[10]
|
||||
{
|
||||
0x58, // pop eax (ret)
|
||||
0x59, // pop ecx (arg1)
|
||||
0x50, // push eax (ret)
|
||||
0xB8, 0, 0, 0, 0, // mov eax, TARGET
|
||||
0xFF, 0xE0 // jmp eax
|
||||
}; // 10 bytes total
|
||||
|
||||
const int TARGET_OFFSET = 4;
|
||||
Unsafe.WriteUnaligned(ref code[TARGET_OFFSET], (uint)target);
|
||||
|
||||
var mem = NativeMethods.VirtualAlloc(0, 10, NativeMethods.MEM_COMMIT | NativeMethods.MEM_RESERVE, NativeMethods.PAGE_EXECUTE_READWRITE);
|
||||
if (mem is 0)
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error(), "VirtualAlloc");
|
||||
}
|
||||
|
||||
Buffer.MemoryCopy(code, (void*)mem, 10, 10);
|
||||
return mem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a thunk for __fastcall with 2+ parameters (ECX and EDX).
|
||||
/// </summary>
|
||||
protected unsafe static nint BuildFastCallThunk2(nuint target)
|
||||
{
|
||||
if (target is 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var code = stackalloc byte[11]
|
||||
{
|
||||
0x58, // pop eax (ret)
|
||||
0x59, // pop ecx (ctx)
|
||||
0x5A, // pop edx (edxVal)
|
||||
0x50, // push eax (ret)
|
||||
0xB8,0,0,0,0, // mov eax, TARGET
|
||||
0xFF,0xE0 // jmp eax
|
||||
}; // 11 bytes total
|
||||
|
||||
const int TARGET_OFFSET = 5;
|
||||
Unsafe.WriteUnaligned(ref code[TARGET_OFFSET], (uint)target);
|
||||
|
||||
var mem = NativeMethods.VirtualAlloc(0, 11, NativeMethods.MEM_COMMIT | NativeMethods.MEM_RESERVE, NativeMethods.PAGE_EXECUTE_READWRITE);
|
||||
if (mem is 0)
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error(), "VirtualAlloc");
|
||||
}
|
||||
|
||||
Buffer.MemoryCopy(code, (void*)mem, 11, 11);
|
||||
return mem;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe sealed class GWFastCall<T1, T2>(GWAddressCache target) : GWFastCall(target)
|
||||
{
|
||||
private delegate* unmanaged[Stdcall]<T1, T2> func = null;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe T2? Invoke(T1 t1)
|
||||
{
|
||||
if (this.func is null)
|
||||
{
|
||||
this.Initialize();
|
||||
}
|
||||
|
||||
if (this.func is not null)
|
||||
{
|
||||
if (typeof(T2) == typeof(Void))
|
||||
{
|
||||
((delegate* unmanaged[Stdcall]<T1, void>)this.func)(t1);
|
||||
return default;
|
||||
}
|
||||
|
||||
return this.func(t1);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
if (this.Cache.GetAddress() is not nuint addr ||
|
||||
addr is 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var call = BuildFastCallThunk1(addr);
|
||||
this.func = (delegate* unmanaged[Stdcall]<T1, T2>)call;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe sealed class GWFastCall<T1, T2, T3>(GWAddressCache target) : GWFastCall(target)
|
||||
{
|
||||
private delegate* unmanaged[Stdcall]<T1, T2, T3> func = null;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe T3? Invoke(T1 t1, T2 t2)
|
||||
{
|
||||
if (this.func is null)
|
||||
{
|
||||
this.Initialize();
|
||||
}
|
||||
|
||||
if (this.func is not null)
|
||||
{
|
||||
if (typeof(T3) == typeof(Void))
|
||||
{
|
||||
((delegate* unmanaged[Stdcall]<T1, T2, void>)this.func)(t1, t2);
|
||||
return default;
|
||||
}
|
||||
|
||||
return this.func(t1, t2);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
if (this.Cache.GetAddress() is not nuint addr ||
|
||||
addr is 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var call = BuildFastCallThunk2(addr);
|
||||
this.func = (delegate* unmanaged[Stdcall]<T1, T2, T3>)call;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe sealed class GWFastCall<T1, T2, T3, T4>(GWAddressCache target) : GWFastCall(target)
|
||||
{
|
||||
private delegate* unmanaged[Stdcall]<T1, T2, T3, T4> func = null;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe T4? Invoke(T1 t1, T2 t2, T3 t3)
|
||||
{
|
||||
if (this.func is null)
|
||||
{
|
||||
this.Initialize();
|
||||
}
|
||||
|
||||
if (this.func is not null)
|
||||
{
|
||||
if (typeof(T4) == typeof(Void))
|
||||
{
|
||||
((delegate* unmanaged[Stdcall]<T1, T2, T3, void>)this.func)(t1, t2, t3);
|
||||
return default;
|
||||
}
|
||||
|
||||
return this.func(t1, t2, t3);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
if (this.Cache.GetAddress() is not nuint addr ||
|
||||
addr is 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var call = BuildFastCallThunk2(addr);
|
||||
this.func = (delegate* unmanaged[Stdcall]<T1, T2, T3, T4>)call;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe sealed class GWFastCall<T1, T2, T3, T4, T5>(GWAddressCache target) : GWFastCall(target)
|
||||
{
|
||||
private delegate* unmanaged[Stdcall]<T1, T2, T3, T4, T5> func = null;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe T5? Invoke(T1 t1, T2 t2, T3 t3, T4 t4)
|
||||
{
|
||||
if (this.func is null)
|
||||
{
|
||||
this.Initialize();
|
||||
}
|
||||
|
||||
if (this.func is not null)
|
||||
{
|
||||
if (typeof(T5) == typeof(Void))
|
||||
{
|
||||
((delegate* unmanaged[Stdcall]<T1, T2, T3, T4, void>)this.func)(t1, t2, t3, t4);
|
||||
return default;
|
||||
}
|
||||
|
||||
return this.func(t1, t2, t3, t4);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
if (this.Cache.GetAddress() is not nuint addr ||
|
||||
addr is 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var call = BuildFastCallThunk2(addr);
|
||||
this.func = (delegate* unmanaged[Stdcall]<T1, T2, T3, T4, T5>)call;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe sealed class GWFastCall<T1, T2, T3, T4, T5, T6>(GWAddressCache target) : GWFastCall(target)
|
||||
{
|
||||
private delegate* unmanaged[Stdcall]<T1, T2, T3, T4, T5, T6> func = null;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe T6? Invoke(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
|
||||
{
|
||||
if (this.func is null)
|
||||
{
|
||||
this.Initialize();
|
||||
}
|
||||
|
||||
if (this.func is not null)
|
||||
{
|
||||
if (typeof(T6) == typeof(Void))
|
||||
{
|
||||
((delegate* unmanaged[Stdcall]<T1, T2, T3, T4, T5, void>)this.func)(t1, t2, t3, t4, t5);
|
||||
return default;
|
||||
}
|
||||
|
||||
return this.func(t1, t2, t3, t4, t5);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
if (this.Cache.GetAddress() is not nuint addr ||
|
||||
addr is 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var call = BuildFastCallThunk2(addr);
|
||||
this.func = (delegate* unmanaged[Stdcall]<T1, T2, T3, T4, T5, T6>)call;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe sealed class GWFastCall<T1, T2, T3, T4, T5, T6, T7>(GWAddressCache target) : GWFastCall(target)
|
||||
{
|
||||
private delegate* unmanaged[Stdcall]<T1, T2, T3, T4, T5, T6, T7> func = null;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe T7? Invoke(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
|
||||
{
|
||||
if (this.func is null)
|
||||
{
|
||||
this.Initialize();
|
||||
}
|
||||
|
||||
if (this.func is not null)
|
||||
{
|
||||
if (typeof(T7) == typeof(Void))
|
||||
{
|
||||
((delegate* unmanaged[Stdcall]<T1, T2, T3, T4, T5, T6, void>)this.func)(t1, t2, t3, t4, t5, t6);
|
||||
return default;
|
||||
}
|
||||
|
||||
return this.func(t1, t2, t3, t4, t5, t6);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
if (this.Cache.GetAddress() is not nuint addr ||
|
||||
addr is 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var call = BuildFastCallThunk2(addr);
|
||||
this.func = (delegate* unmanaged[Stdcall]<T1, T2, T3, T4, T5, T6, T7>)call;
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using MinHook;
|
||||
|
||||
namespace Daybreak.API.Interop;
|
||||
|
||||
/// <summary>
|
||||
/// A thin convenience wrapper around MinHook that
|
||||
/// resolves the target address lazily through <see cref="GWAddressCache"/>
|
||||
/// unwraps an existing “CALL/JMP rel32” stub so we patch the real code
|
||||
/// exposes <see cref="Original"/> so your detour can chain
|
||||
/// </summary>
|
||||
public sealed class GWHook<T>(
|
||||
GWAddressCache funcAddress,
|
||||
T detour,
|
||||
bool bypassPreviousHooks = false) : IHook<T>
|
||||
where T : Delegate
|
||||
{
|
||||
private readonly bool bypassPreviousHooks = bypassPreviousHooks;
|
||||
private readonly GWAddressCache addressCache = funcAddress ?? throw new ArgumentNullException(nameof(funcAddress));
|
||||
private readonly T detour = detour ?? throw new ArgumentNullException(nameof(detour));
|
||||
private readonly SemaphoreSlim semaphore = new(1, 1);
|
||||
|
||||
private T? cont; // trampoline returned by MinHook
|
||||
private HookEngine? engine;
|
||||
|
||||
/// <summary>Delegate that calls the next hook / real function.</summary>
|
||||
public T Continue => this.cont ??
|
||||
throw new InvalidOperationException("Hook not initialised – call EnsureInitialized() first.");
|
||||
|
||||
public bool Hooked { get; private set; } = false;
|
||||
public nuint TargetAddress { get; private set; }
|
||||
public nuint ContinueAddress { get; private set; }
|
||||
public nuint DetourAddress { get; private set; }
|
||||
|
||||
/// <summary>Installs the hook exactly once (thread-safe).</summary>
|
||||
public bool EnsureInitialized()
|
||||
{
|
||||
if (this.Hooked)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
this.semaphore.Wait();
|
||||
try
|
||||
{
|
||||
if (this.Hooked)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var addr = this.addressCache.GetAddress();
|
||||
if (addr.HasValue is false ||
|
||||
addr.Value is 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var target = this.bypassPreviousHooks
|
||||
? UnwrapNearBranch(addr.Value)
|
||||
: addr.Value;
|
||||
if (target is 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
this.engine = new HookEngine();
|
||||
this.cont = this.engine.CreateHook((nint)target, this.detour);
|
||||
this.engine.EnableHooks();
|
||||
this.TargetAddress = target;
|
||||
this.ContinueAddress = (nuint)this.cont.Method.MethodHandle.GetFunctionPointer();
|
||||
this.DetourAddress = (nuint)this.detour.Method.MethodHandle.GetFunctionPointer();
|
||||
this.Hooked = true;
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.semaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.semaphore.Wait();
|
||||
try
|
||||
{
|
||||
if (!this.Hooked ||
|
||||
this.engine is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.engine.DisableHooks();
|
||||
this.engine.Dispose();
|
||||
|
||||
this.cont = null;
|
||||
this.Hooked = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.semaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Follows a <c>CALL rel32</c> (<c>E8</c>) **or** <c>JMP rel32</c> (<c>E9</c>)
|
||||
/// trampoline that may have been planted by a previous hook.
|
||||
/// </summary>
|
||||
private static unsafe nuint UnwrapNearBranch(nuint addr)
|
||||
{
|
||||
byte op = Marshal.ReadByte((IntPtr)addr);
|
||||
if (op != 0xE8 && op != 0xE9) // not CALL/JMP rel32
|
||||
return addr;
|
||||
|
||||
int rel = Marshal.ReadInt32((IntPtr)(addr + 1));
|
||||
long dst = (long)addr + 5 + rel; // 5-byte instruction
|
||||
return (nuint)dst;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0xC)]
|
||||
public readonly struct AccountUnlockedCount
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly uint Id;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x138)]
|
||||
[GWCAEquivalent("AccountContext")]
|
||||
public readonly struct AccountGameContext
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly GuildWarsArray<AccountUnlockedCount> AccountUnlockedCounts;
|
||||
|
||||
[FieldOffset(0x00b4)]
|
||||
public readonly GuildWarsArray<uint> UnlockedPvpHeroes;
|
||||
|
||||
[FieldOffset(0x0124)]
|
||||
public readonly GuildWarsArray<uint> UnlockedAccountSkills;
|
||||
|
||||
[FieldOffset(0x0134)]
|
||||
public readonly uint AccountFlags;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x1C)]
|
||||
[GWCAEquivalent("AccountInfo")]
|
||||
public readonly unsafe struct AccountInfoContext
|
||||
{
|
||||
public readonly char* AccountName;
|
||||
public readonly uint Wins;
|
||||
public readonly uint Losses;
|
||||
public readonly uint Rating;
|
||||
public readonly uint QualifierPoints;
|
||||
public readonly uint Rank;
|
||||
public readonly uint TournamentRewardPoints;
|
||||
}
|
||||
@@ -1,254 +0,0 @@
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[Flags]
|
||||
public enum AgentType : uint
|
||||
{
|
||||
Living = 0xDB,
|
||||
Gadget = 0x200,
|
||||
Item = 0x400
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum AgentModelType : ushort
|
||||
{
|
||||
NPC = 0x2000,
|
||||
Player = 0x3000
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum LivingAgentState : uint
|
||||
{
|
||||
None = 0,
|
||||
InCombatStance = 0x000001,
|
||||
HasQuest = 0x000002,
|
||||
Dead = 0x000008,
|
||||
Female = 0x000200,
|
||||
HasBossGlow = 0x000400,
|
||||
HidingCape = 0x001000,
|
||||
CanBeViewedInPartyWindow = 0x020000,
|
||||
SpawnedSpirit = 0x040000,
|
||||
BeingObservedOrPlayer = 0x400000
|
||||
}
|
||||
|
||||
public enum LivingAgentAllegiance : byte
|
||||
{
|
||||
Ally_NonAttackable = 0x1,
|
||||
Neutral = 0x2,
|
||||
Enemy = 0x3,
|
||||
Spirit_Pet = 0x4,
|
||||
Minion = 0x5,
|
||||
Npc_Minipet = 0x6
|
||||
};
|
||||
|
||||
|
||||
[Flags]
|
||||
public enum LivingAgentEffects : uint
|
||||
{
|
||||
None = 0,
|
||||
Bleeding = 0x0001,
|
||||
Conditioned = 0x0002,
|
||||
Crippled1 = 0x0008, // Part of the Crippled check
|
||||
Crippled = 0x000A, // Combined flag for crippled (0x0008 | 0x0002)
|
||||
Dead = 0x0010,
|
||||
DeepWound = 0x0020,
|
||||
Poisoned = 0x0040,
|
||||
Enchanted = 0x0080,
|
||||
DegenHexed = 0x0400,
|
||||
Hexed = 0x0800,
|
||||
WeaponSpelled = 0x8000
|
||||
}
|
||||
|
||||
public enum LivingAgentModelState : ushort
|
||||
{
|
||||
// Idle states
|
||||
Idle1 = 64,
|
||||
Idle2 = 68,
|
||||
Idle3 = 100,
|
||||
|
||||
// Casting states
|
||||
Casting1 = 65,
|
||||
Casting2 = 581,
|
||||
|
||||
// Moving states
|
||||
Moving1 = 12,
|
||||
Moving2 = 76,
|
||||
Moving3 = 204,
|
||||
|
||||
// Attacking states
|
||||
Attacking1 = 96,
|
||||
Attacking2 = 1088,
|
||||
Attacking3 = 1120,
|
||||
|
||||
// Other states
|
||||
KnockedDown = 1104
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[GWCAEquivalent("AgentEffects")]
|
||||
public readonly struct AgentEffects
|
||||
{
|
||||
public readonly uint AgentId;
|
||||
public readonly GuildWarsArray<Buff> Buffs;
|
||||
public readonly GuildWarsArray<Effect> Effects;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
[GWCAEquivalent("AgentContext")]
|
||||
public readonly struct AgentGameContext
|
||||
{
|
||||
[FieldOffset(0x01AC)]
|
||||
public readonly uint InstanceTimer;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 196)]
|
||||
[GWCAEquivalent("Agent")]
|
||||
public readonly struct AgentContext
|
||||
{
|
||||
[FieldOffset(0x0014)]
|
||||
public readonly uint AgentInstanceTimer;
|
||||
|
||||
[FieldOffset(0x002C)]
|
||||
public readonly uint AgentId;
|
||||
|
||||
[FieldOffset(0x0074)]
|
||||
public readonly GamePos Pos;
|
||||
|
||||
[FieldOffset(0x009C)]
|
||||
public readonly AgentType Type;
|
||||
|
||||
[FieldOffset(0x00A0)]
|
||||
public readonly Vector2 Velocity;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 212)]
|
||||
[GWCAEquivalent("AgentItem")]
|
||||
public readonly struct AgentItemContext
|
||||
{
|
||||
[FieldOffset(0x00C4)]
|
||||
public readonly uint OwnerId;
|
||||
|
||||
[FieldOffset(0x00C8)]
|
||||
public readonly uint ItemId;
|
||||
|
||||
[FieldOffset(0x00D0)]
|
||||
public readonly uint ExtraType;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 228)]
|
||||
[GWCAEquivalent("AgentGadget")]
|
||||
public readonly struct AgentGadgetContext
|
||||
{
|
||||
[FieldOffset(0x00CC)]
|
||||
public readonly uint ExtraType;
|
||||
|
||||
[FieldOffset(0x00D0)]
|
||||
public readonly uint GadgetId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x1C0)]
|
||||
[GWCAEquivalent("AgentLiving")]
|
||||
public readonly unsafe struct AgentLivingContext
|
||||
{
|
||||
[FieldOffset(0x00C4)]
|
||||
public readonly uint OwnerId;
|
||||
|
||||
[FieldOffset(0x00F4)]
|
||||
public readonly ushort AgentType; // All non-player have an identifier. Two of the same mob have the same identifier;
|
||||
|
||||
[FieldOffset(0x00F6)]
|
||||
public readonly AgentModelType AgentModelType;
|
||||
|
||||
[FieldOffset(0x0108)]
|
||||
public readonly TagInfo* Tags;
|
||||
|
||||
[FieldOffset(0x010E)]
|
||||
public readonly byte Primary;
|
||||
|
||||
[FieldOffset(0x010F)]
|
||||
public readonly byte Secondary;
|
||||
|
||||
[FieldOffset(0x0110)]
|
||||
public readonly byte Level;
|
||||
|
||||
[FieldOffset(0x0111)]
|
||||
public readonly byte TeamId;
|
||||
|
||||
[FieldOffset(0x0118)]
|
||||
public readonly float EnergyRegen;
|
||||
|
||||
[FieldOffset(0x0120)]
|
||||
public readonly float Energy;
|
||||
|
||||
[FieldOffset(0x0124)]
|
||||
public readonly uint MaxEnergy;
|
||||
|
||||
[FieldOffset(0x012C)]
|
||||
public readonly float HealthRegen;
|
||||
|
||||
[FieldOffset(0x0134)]
|
||||
public readonly float Health;
|
||||
|
||||
[FieldOffset(0x0138)]
|
||||
public readonly uint MaxHealth;
|
||||
|
||||
[FieldOffset(0x013C)]
|
||||
public readonly uint Effects;
|
||||
|
||||
[FieldOffset(0x0158)]
|
||||
public readonly LivingAgentModelState ModelState;
|
||||
|
||||
[FieldOffset(0x015C)]
|
||||
public readonly LivingAgentState State;
|
||||
|
||||
[FieldOffset(0x0184)]
|
||||
public readonly uint LoginNumber;
|
||||
|
||||
[FieldOffset(0x01B5)]
|
||||
public readonly LivingAgentAllegiance Allegiance;
|
||||
|
||||
public readonly bool IsAlive => (!this.State.HasFlag(LivingAgentState.Dead)) && this.Health > 0f;
|
||||
|
||||
public readonly bool IsPlayer => this.LoginNumber is not 0;
|
||||
|
||||
public readonly bool IsNpc => this.LoginNumber is 0;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 52)]
|
||||
[GWCAEquivalent("MapAgent")]
|
||||
public readonly struct MapAgentContext
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly float CurrentEnergy;
|
||||
|
||||
[FieldOffset(0x0004)]
|
||||
public readonly float MaxEnergy;
|
||||
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly float EnergyRegen;
|
||||
|
||||
[FieldOffset(0x000C)]
|
||||
public readonly uint SkillTimestamp;
|
||||
|
||||
[FieldOffset(0x0020)]
|
||||
public readonly float CurrentHealth;
|
||||
|
||||
[FieldOffset(0x0024)]
|
||||
public readonly float MaxHealth;
|
||||
|
||||
[FieldOffset(0x0028)]
|
||||
public readonly float HealthRegen;
|
||||
|
||||
[FieldOffset(0x0030)]
|
||||
public readonly LivingAgentEffects Effects;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x38)]
|
||||
[GWCAEquivalent("AgentInfo")]
|
||||
public readonly unsafe struct AgentInfo
|
||||
{
|
||||
[FieldOffset(0x0034)]
|
||||
public readonly char* NameEncoded;
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[GWCAEquivalent("Attribute")]
|
||||
public readonly struct AttributeContext
|
||||
{
|
||||
public readonly uint Id;
|
||||
public readonly uint LevelBase;
|
||||
public readonly uint Level;
|
||||
public readonly uint DecrementPoints;
|
||||
public readonly uint IncrementPoints;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[GWCAEquivalent("AttributeInfo")]
|
||||
public readonly struct AttributeInfo
|
||||
{
|
||||
public readonly uint ProfessionId;
|
||||
public readonly uint AttributeId;
|
||||
public readonly uint NameId;
|
||||
public readonly uint DescriptionId;
|
||||
public readonly uint IsPve;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[GWCAEquivalent("PartyAttribute")]
|
||||
public readonly struct PartyAttribute
|
||||
{
|
||||
public readonly uint AgentId;
|
||||
public readonly AttributeContext Attribute0;
|
||||
public readonly AttributeContext Attribute1;
|
||||
public readonly AttributeContext Attribute2;
|
||||
public readonly AttributeContext Attribute3;
|
||||
public readonly AttributeContext Attribute4;
|
||||
public readonly AttributeContext Attribute5;
|
||||
public readonly AttributeContext Attribute6;
|
||||
public readonly AttributeContext Attribute7;
|
||||
public readonly AttributeContext Attribute8;
|
||||
public readonly AttributeContext Attribute9;
|
||||
public readonly AttributeContext Attribute10;
|
||||
public readonly AttributeContext Attribute11;
|
||||
public readonly AttributeContext Attribute12;
|
||||
public readonly AttributeContext Attribute13;
|
||||
public readonly AttributeContext Attribute14;
|
||||
public readonly AttributeContext Attribute15;
|
||||
public readonly AttributeContext Attribute16;
|
||||
public readonly AttributeContext Attribute17;
|
||||
public readonly AttributeContext Attribute18;
|
||||
public readonly AttributeContext Attribute19;
|
||||
public readonly AttributeContext Attribute20;
|
||||
public readonly AttributeContext Attribute21;
|
||||
public readonly AttributeContext Attribute22;
|
||||
public readonly AttributeContext Attribute23;
|
||||
public readonly AttributeContext Attribute24;
|
||||
public readonly AttributeContext Attribute25;
|
||||
public readonly AttributeContext Attribute26;
|
||||
public readonly AttributeContext Attribute27;
|
||||
public readonly AttributeContext Attribute28;
|
||||
public readonly AttributeContext Attribute29;
|
||||
public readonly AttributeContext Attribute30;
|
||||
public readonly AttributeContext Attribute31;
|
||||
public readonly AttributeContext Attribute32;
|
||||
public readonly AttributeContext Attribute33;
|
||||
public readonly AttributeContext Attribute34;
|
||||
public readonly AttributeContext Attribute35;
|
||||
public readonly AttributeContext Attribute36;
|
||||
public readonly AttributeContext Attribute37;
|
||||
public readonly AttributeContext Attribute38;
|
||||
public readonly AttributeContext Attribute39;
|
||||
public readonly AttributeContext Attribute40;
|
||||
public readonly AttributeContext Attribute41;
|
||||
public readonly AttributeContext Attribute42;
|
||||
public readonly AttributeContext Attribute43;
|
||||
public readonly AttributeContext Attribute44;
|
||||
public readonly AttributeContext Attribute45;
|
||||
public readonly AttributeContext Attribute46;
|
||||
public readonly AttributeContext Attribute47;
|
||||
public readonly AttributeContext Attribute48;
|
||||
public readonly AttributeContext Attribute49;
|
||||
public readonly AttributeContext Attribute50;
|
||||
public readonly AttributeContext Attribute51;
|
||||
public readonly AttributeContext Attribute52;
|
||||
public readonly AttributeContext Attribute53;
|
||||
|
||||
public readonly AttributeContext[] Attributes =>
|
||||
[
|
||||
this.Attribute0, this.Attribute1, this.Attribute2, this.Attribute3, this.Attribute4, this.Attribute5, this.Attribute6, this.Attribute7, this.Attribute8, this.Attribute9,
|
||||
this.Attribute10, this.Attribute11, this.Attribute12, this.Attribute13, this.Attribute14, this.Attribute15, this.Attribute16, this.Attribute17, this.Attribute18, this.Attribute19,
|
||||
this.Attribute20, this.Attribute21, this.Attribute22, this.Attribute23, this.Attribute24, this.Attribute25, this.Attribute26, this.Attribute27, this.Attribute28, this.Attribute29,
|
||||
this.Attribute30, this.Attribute31, this.Attribute32, this.Attribute33, this.Attribute34, this.Attribute35, this.Attribute36, this.Attribute37, this.Attribute38, this.Attribute39,
|
||||
this.Attribute40, this.Attribute41, this.Attribute42, this.Attribute43, this.Attribute44, this.Attribute45, this.Attribute46, this.Attribute47, this.Attribute48, this.Attribute49,
|
||||
this.Attribute50, this.Attribute51, this.Attribute52, this.Attribute53
|
||||
];
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
public enum BagType
|
||||
{
|
||||
None,
|
||||
Inventory,
|
||||
Equipped,
|
||||
NotCollected,
|
||||
Storage,
|
||||
MaterialsStorage
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
[GWCAEquivalent("Bag")]
|
||||
public readonly unsafe struct Bag
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly BagType Type;
|
||||
[FieldOffset(0x0004)]
|
||||
public readonly uint Index;
|
||||
[FieldOffset(0x000C)]
|
||||
public readonly uint ContainerItem;
|
||||
[FieldOffset(0x0010)]
|
||||
public readonly uint ItemsCount;
|
||||
[FieldOffset(0x0014)]
|
||||
public readonly Bag* Bags;
|
||||
[FieldOffset(0x0018)]
|
||||
public readonly GuildWarsArray<WrappedPointer<Item>> Items;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[GWCAEquivalent("HeroBehavior")]
|
||||
public enum Behavior
|
||||
{
|
||||
Fight,
|
||||
Guard,
|
||||
AvoidCombat
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
using System.Extensions;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
[GWCAEquivalent("CharContext")]
|
||||
public readonly struct CharContext
|
||||
{
|
||||
[FieldOffset(0x0064)]
|
||||
public readonly Uuid PlayerUuid;
|
||||
|
||||
[FieldOffset(0x0074)]
|
||||
public readonly Array20Char PlayerName;
|
||||
|
||||
[FieldOffset(0x0198)]
|
||||
public readonly uint MapId;
|
||||
|
||||
[FieldOffset(0x019C)]
|
||||
public readonly uint IsExporable;
|
||||
|
||||
[FieldOffset(0x01A0)]
|
||||
public readonly Array24Byte Host;
|
||||
|
||||
[FieldOffset(0x01B8)]
|
||||
public readonly uint PlayerId;
|
||||
|
||||
[FieldOffset(0x0220)]
|
||||
public readonly uint DistrictNumber;
|
||||
|
||||
[FieldOffset(0x0224)]
|
||||
public readonly Language Language;
|
||||
|
||||
[FieldOffset(0x0228)]
|
||||
public readonly uint ObserveMapId;
|
||||
|
||||
[FieldOffset(0x022C)]
|
||||
public readonly uint CurrentMapId;
|
||||
|
||||
[FieldOffset(0x0230)]
|
||||
public readonly uint ObserveMapType;
|
||||
|
||||
[FieldOffset(0x0234)]
|
||||
public readonly uint CurrentMapType;
|
||||
|
||||
[FieldOffset(0x02A4)]
|
||||
public readonly uint PlayerNumber;
|
||||
|
||||
[FieldOffset(0x03B8)]
|
||||
public readonly Array64Char PlayerEmail;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using System.Extensions;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
[GWCAEquivalent("CharacterInformation")]
|
||||
public readonly struct CharInfoContext
|
||||
{
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly Uuid Uuid;
|
||||
[FieldOffset(0x0018)]
|
||||
public readonly Array20Char Name;
|
||||
[FieldOffset(0x0040)]
|
||||
public readonly Array17Uint Props;
|
||||
|
||||
public readonly uint MapId => (this.Props[0] >> 16) & 0xFFFF;
|
||||
public readonly uint Primary => (this.Props[2] >> 20) & 0xF;
|
||||
public readonly uint Secondary => (this.Props[7] >> 10) & 0xF;
|
||||
public readonly uint Campaign => this.Props[7] & 0xF;
|
||||
public readonly uint Level => (this.Props[7] >> 4) & 0x3F;
|
||||
public readonly bool IsPvp => ((this.Props[7] >> 9) & 0x1) == 0x1;
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[GWCAEquivalent("ControlAction")]
|
||||
public enum ControlAction : uint
|
||||
{
|
||||
None = 0,
|
||||
Screenshot = 0xAE,
|
||||
|
||||
// Panels
|
||||
CloseAllPanels = 0x85,
|
||||
ToggleInventoryWindow = 0x8B,
|
||||
OpenScoreChart = 0xBD,
|
||||
OpenTemplateManager = 0xD3,
|
||||
OpenSaveEquipmentTemplate = 0xD4,
|
||||
OpenSaveSkillTemplate = 0xD5,
|
||||
OpenParty = 0xBF,
|
||||
OpenGuild = 0xBA,
|
||||
OpenFriends = 0xB9,
|
||||
ToggleAllBags = 0xB8,
|
||||
OpenMissionMap = 0xB6,
|
||||
OpenBag2 = 0xB5,
|
||||
OpenBag1 = 0xB4,
|
||||
OpenBelt = 0xB3,
|
||||
OpenBackpack = 0xB2,
|
||||
OpenSkillsAndAttributes = 0x8F,
|
||||
OpenQuestLog = 0x8E,
|
||||
OpenWorldMap = 0x8C,
|
||||
OpenOptions = 0x8D,
|
||||
OpenHero = 0x8A,
|
||||
|
||||
// Weapon sets
|
||||
CycleEquipment = 0x86,
|
||||
ActivateWeaponSet1 = 0x81,
|
||||
ActivateWeaponSet2,
|
||||
ActivateWeaponSet3,
|
||||
ActivateWeaponSet4,
|
||||
|
||||
DropItem = 0xCD, // drops bundle item >> flags, ashes, etc
|
||||
|
||||
// Chat
|
||||
CharReply = 0xBE,
|
||||
OpenChat = 0xA1,
|
||||
OpenAlliance = 0x88,
|
||||
|
||||
ReverseCamera = 0x90,
|
||||
StrafeLeft = 0x91,
|
||||
StrafeRight = 0x92,
|
||||
TurnLeft = 0xA2,
|
||||
TurnRight = 0xA3,
|
||||
MoveBackward = 0xAC,
|
||||
MoveForward = 0xAD,
|
||||
CancelAction = 0xAF,
|
||||
Interact = 0x80,
|
||||
ReverseDirection = 0xB1,
|
||||
Autorun = 0xB7,
|
||||
Follow = 0xCC,
|
||||
|
||||
// Targeting
|
||||
TargetPartyMember1 = 0x96,
|
||||
TargetPartyMember2,
|
||||
TargetPartyMember3,
|
||||
TargetPartyMember4,
|
||||
TargetPartyMember5,
|
||||
TargetPartyMember6,
|
||||
TargetPartyMember7,
|
||||
TargetPartyMember8,
|
||||
TargetPartyMember9 = 0xC6,
|
||||
TargetPartyMember10,
|
||||
TargetPartyMember11,
|
||||
TargetPartyMember12,
|
||||
|
||||
TargetNearestItem = 0xC3,
|
||||
TargetNextItem = 0xC4,
|
||||
TargetPreviousItem = 0xC5,
|
||||
TargetPartyMemberNext = 0xCA,
|
||||
TargetPartyMemberPrevious = 0xCB,
|
||||
TargetAllyNearest = 0xBC,
|
||||
ClearTarget = 0xE3,
|
||||
TargetSelf = 0xA0, // also 0x96
|
||||
TargetPriorityTarget = 0x9F,
|
||||
TargetNearestEnemy = 0x93,
|
||||
TargetNextEnemy = 0x95,
|
||||
TargetPreviousEnemy = 0x9E,
|
||||
|
||||
ShowOthers = 0x89,
|
||||
ShowTargets = 0x94,
|
||||
|
||||
CameraZoomIn = 0xCE,
|
||||
CameraZoomOut = 0xCF,
|
||||
|
||||
// Party/Hero commands
|
||||
ClearPartyCommands = 0xDB,
|
||||
CommandParty = 0xD6,
|
||||
CommandHero1,
|
||||
CommandHero2,
|
||||
CommandHero3,
|
||||
CommandHero4 = 0x102,
|
||||
CommandHero5,
|
||||
CommandHero6,
|
||||
CommandHero7,
|
||||
|
||||
OpenHero1PetCommander = 0xE0,
|
||||
OpenHero2PetCommander,
|
||||
OpenHero3PetCommander,
|
||||
OpenHero4PetCommander = 0xFE,
|
||||
OpenHero5PetCommander,
|
||||
OpenHero6PetCommander,
|
||||
OpenHero7PetCommander,
|
||||
OpenHeroCommander1 = 0xDC,
|
||||
OpenHeroCommander2,
|
||||
OpenHeroCommander3,
|
||||
OpenPetCommander,
|
||||
OpenHeroCommander4 = 0x126,
|
||||
OpenHeroCommander5,
|
||||
OpenHeroCommander6,
|
||||
OpenHeroCommander7,
|
||||
|
||||
Hero1Skill1 = 0xE5,
|
||||
Hero1Skill2,
|
||||
Hero1Skill3,
|
||||
Hero1Skill4,
|
||||
Hero1Skill5,
|
||||
Hero1Skill6,
|
||||
Hero1Skill7,
|
||||
Hero1Skill8,
|
||||
Hero2Skill1,
|
||||
Hero2Skill2,
|
||||
Hero2Skill3,
|
||||
Hero2Skill4,
|
||||
Hero2Skill5,
|
||||
Hero2Skill6,
|
||||
Hero2Skill7,
|
||||
Hero2Skill8,
|
||||
Hero3Skill1,
|
||||
Hero3Skill2,
|
||||
Hero3Skill3,
|
||||
Hero3Skill4,
|
||||
Hero3Skill5,
|
||||
Hero3Skill6,
|
||||
Hero3Skill7,
|
||||
Hero3Skill8,
|
||||
Hero4Skill1 = 0x106,
|
||||
Hero4Skill2,
|
||||
Hero4Skill3,
|
||||
Hero4Skill4,
|
||||
Hero4Skill5,
|
||||
Hero4Skill6,
|
||||
Hero4Skill7,
|
||||
Hero4Skill8,
|
||||
Hero5Skill1,
|
||||
Hero5Skill2,
|
||||
Hero5Skill3,
|
||||
Hero5Skill4,
|
||||
Hero5Skill5,
|
||||
Hero5Skill6,
|
||||
Hero5Skill7,
|
||||
Hero5Skill8,
|
||||
Hero6Skill1,
|
||||
Hero6Skill2,
|
||||
Hero6Skill3,
|
||||
Hero6Skill4,
|
||||
Hero6Skill5,
|
||||
Hero6Skill6,
|
||||
Hero6Skill7,
|
||||
Hero6Skill8,
|
||||
Hero7Skill1,
|
||||
Hero7Skill2,
|
||||
Hero7Skill3,
|
||||
Hero7Skill4,
|
||||
Hero7Skill5,
|
||||
Hero7Skill6,
|
||||
Hero7Skill7,
|
||||
Hero7Skill8,
|
||||
|
||||
// Skills
|
||||
UseSkill1 = 0xA4,
|
||||
UseSkill2,
|
||||
UseSkill3,
|
||||
UseSkill4,
|
||||
UseSkill5,
|
||||
UseSkill6,
|
||||
UseSkill7,
|
||||
UseSkill8
|
||||
};
|
||||
@@ -1,20 +0,0 @@
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[GWCAEquivalent("District")]
|
||||
public enum District
|
||||
{
|
||||
Current,
|
||||
International,
|
||||
American,
|
||||
EuropeEnglish,
|
||||
EuropeFrench,
|
||||
EuropeGerman,
|
||||
EuropeItalian,
|
||||
EuropeSpanish,
|
||||
EuropePolish,
|
||||
EuropeRussian,
|
||||
AsiaKorean,
|
||||
AsiaChinese,
|
||||
AsiaJapanese,
|
||||
Unknown = 0xff
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
using Daybreak.API.Models;
|
||||
using System.Extensions;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
// Very incomplete. GWCA contains a much better definition
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x1AC)]
|
||||
[GWCAEquivalent("Frame")]
|
||||
public readonly struct Frame
|
||||
{
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly uint FrameLayout;
|
||||
|
||||
[FieldOffset(0x0018)]
|
||||
public readonly uint VisibilityFlags;
|
||||
|
||||
[FieldOffset(0x0020)]
|
||||
public readonly uint Type;
|
||||
|
||||
[FieldOffset(0x0024)]
|
||||
public readonly uint TemplateType;
|
||||
|
||||
[FieldOffset(0x00A8)]
|
||||
public readonly GuildWarsArray<FrameInteractionCallback> FrameCallbacks;
|
||||
|
||||
[FieldOffset(0x00b8)]
|
||||
public readonly uint ChildOffsetId;
|
||||
|
||||
[FieldOffset(0x00bc)]
|
||||
public readonly uint FrameId;
|
||||
|
||||
[FieldOffset(0x0128)]
|
||||
public readonly FrameRelation Relation;
|
||||
|
||||
[FieldOffset(0x018C)]
|
||||
public readonly uint FrameState;
|
||||
|
||||
public bool IsCreated => (this.FrameState & 0x4) != 0;
|
||||
public bool IsHidden => (this.FrameState & 0x200) != 0;
|
||||
public bool IsVisible => !this.IsHidden;
|
||||
public bool IsDIsabled => (this.FrameState & 0x10) != 0;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x1C)]
|
||||
public readonly unsafe struct FrameRelation
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly FrameRelation* Parent;
|
||||
|
||||
[FieldOffset(0x000C)]
|
||||
public readonly uint FrameHashId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public readonly unsafe struct InteractionMessage
|
||||
{
|
||||
public readonly uint FrameId;
|
||||
public readonly UIMessage MessageId;
|
||||
public readonly void** WParam;
|
||||
}
|
||||
|
||||
public unsafe delegate void UIInteractionCallback(InteractionMessage* message, void* wParam, void* lParam);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0xC)]
|
||||
public unsafe readonly struct FrameInteractionCallback
|
||||
{
|
||||
public readonly void* Callback; // UIInteractionCallback
|
||||
public readonly void* UiCtl_Context;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
public readonly unsafe struct CharSelectorContext
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly uint Vtable;
|
||||
|
||||
[FieldOffset(0x0004)]
|
||||
public readonly uint FrameId;
|
||||
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly GuildWarsArray<WrappedPointer<CharSelectorChar>> Chars;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
public readonly struct CharSelectorChar
|
||||
{
|
||||
[FieldOffset(0x0020)]
|
||||
public readonly Array20Char Name;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
[GWCAEquivalent("GameContext")]
|
||||
public readonly unsafe struct GameContext
|
||||
{
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly AgentGameContext* AgentGameContext;
|
||||
|
||||
[FieldOffset(0x0014)]
|
||||
public readonly MapContext* MapContext;
|
||||
|
||||
[FieldOffset(0x0018)]
|
||||
public readonly TextParserContext* TextParserContext;
|
||||
|
||||
[FieldOffset(0x0028)]
|
||||
public readonly AccountGameContext* AccountContext;
|
||||
|
||||
[FieldOffset(0x002C)]
|
||||
public readonly WorldContext* WorldContext;
|
||||
|
||||
[FieldOffset(0x003C)]
|
||||
public readonly GuildContext* GuildContext;
|
||||
|
||||
[FieldOffset(0x0040)]
|
||||
public readonly ItemContext* ItemContext;
|
||||
|
||||
[FieldOffset(0x0044)]
|
||||
public readonly CharContext* CharContext;
|
||||
|
||||
[FieldOffset(0x004C)]
|
||||
public readonly PartyContext* PartyContext;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[GWCAEquivalent("GamePos")]
|
||||
public readonly struct GamePos
|
||||
{
|
||||
public readonly float X;
|
||||
public readonly float Y;
|
||||
public readonly uint Plane;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x78)]
|
||||
[GWCAEquivalent("GameplayContext")]
|
||||
public readonly struct GameplayContext
|
||||
{
|
||||
[FieldOffset(0x4C)]
|
||||
public readonly float MissionMapZoom;
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
using System.Extensions;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
[GWCAEquivalent("GuildContext")]
|
||||
public readonly struct GuildContext
|
||||
{
|
||||
[FieldOffset(0x0034)]
|
||||
public readonly Array20Char PlayerName;
|
||||
|
||||
[FieldOffset(0x0060)]
|
||||
public readonly uint PlayerBuildIndex;
|
||||
|
||||
[FieldOffset(0x0078)]
|
||||
public readonly Array256Char Announcement;
|
||||
|
||||
[FieldOffset(0x0287)]
|
||||
public readonly Array20Char AnnouncementAuthor;
|
||||
|
||||
[FieldOffset(0x02A0)]
|
||||
public readonly uint PlayerGuildRank;
|
||||
|
||||
[FieldOffset(0x02A8)]
|
||||
public readonly GuildWarsArray<TownAlliance> FactionOutpostGuilds;
|
||||
|
||||
[FieldOffset(0x02B8)]
|
||||
public readonly uint KurzickTownCount;
|
||||
|
||||
[FieldOffset(0x02BC)]
|
||||
public readonly uint LuxonTownCount;
|
||||
|
||||
[FieldOffset(0x02F8)]
|
||||
public readonly GuildWarsArray<WrappedPointer<Guild>> Guilds;
|
||||
|
||||
[FieldOffset(0x0358)]
|
||||
public readonly GuildWarsArray<WrappedPointer<GuildPlayer>> PlayerRoster;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public readonly struct TownAlliance
|
||||
{
|
||||
public readonly uint Rank;
|
||||
public readonly uint Allegiance;
|
||||
public readonly uint Faction;
|
||||
public readonly Array32Char Name;
|
||||
public readonly Array5Char Tag;
|
||||
public readonly CapeDesign Cape;
|
||||
public readonly uint MapId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public readonly struct CapeDesign
|
||||
{
|
||||
public readonly uint CapeBgColor;
|
||||
public readonly uint CapeDetailColor;
|
||||
public readonly uint CapeEmblemColor;
|
||||
public readonly uint CapeShape;
|
||||
public readonly uint CapeDetail;
|
||||
public readonly uint CapeEmblem;
|
||||
public readonly uint CapeTrim;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x174)]
|
||||
public readonly unsafe struct GuildPlayer
|
||||
{
|
||||
[FieldOffset(0x0004)]
|
||||
public readonly char* NamePtr;
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly Array20Char InvitedName;
|
||||
[FieldOffset(0x0030)]
|
||||
public readonly Array20Char CurrentName;
|
||||
[FieldOffset(0x0050)]
|
||||
public readonly Array20Char InviterName;
|
||||
[FieldOffset(0x0080)]
|
||||
public readonly uint InviteTime;
|
||||
[FieldOffset(0x0084)]
|
||||
public readonly Array20Char PromoterName;
|
||||
[FieldOffset(0x00DC)]
|
||||
public readonly uint Offline;
|
||||
[FieldOffset(0x00E0)]
|
||||
public readonly uint MemberType;
|
||||
[FieldOffset(0x00E4)]
|
||||
public readonly uint Status;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0xAC)]
|
||||
public readonly struct Guild
|
||||
{
|
||||
[FieldOffset(0x0024)]
|
||||
public readonly uint Index;
|
||||
[FieldOffset(0x0028)]
|
||||
public readonly uint Rank;
|
||||
[FieldOffset(0x002C)]
|
||||
public readonly uint Features;
|
||||
[FieldOffset(0x0030)]
|
||||
public readonly Array32Char Name;
|
||||
[FieldOffset(0x0070)]
|
||||
public readonly uint Rating;
|
||||
[FieldOffset(0x0074)]
|
||||
public readonly uint Faction;
|
||||
[FieldOffset(0x0078)]
|
||||
public readonly uint FactionPoints;
|
||||
[FieldOffset(0x007C)]
|
||||
public readonly uint QualifierPoints;
|
||||
[FieldOffset(0x0080)]
|
||||
public readonly Array8Char Tag;
|
||||
[FieldOffset(0x0090)]
|
||||
public readonly CapeDesign Cape;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
using System.Extensions;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x24)]
|
||||
public readonly struct HeroFlag
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly uint HeroId;
|
||||
[FieldOffset(0x0004)]
|
||||
public readonly uint AgentId;
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly uint Level;
|
||||
[FieldOffset(0x000C)]
|
||||
public readonly Behavior Behavior;
|
||||
[FieldOffset(0x0010)]
|
||||
public readonly Vector2 Flag;
|
||||
[FieldOffset(0x0020)]
|
||||
public readonly uint LockedTargetId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x78)]
|
||||
[GWCAEquivalent("HeroInfo")]
|
||||
public readonly struct HeroInfo
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly uint HeroId;
|
||||
[FieldOffset(0x0004)]
|
||||
public readonly uint AgentId;
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly uint Level;
|
||||
[FieldOffset(0x000C)]
|
||||
public readonly Profession Primary;
|
||||
[FieldOffset(0x0010)]
|
||||
public readonly Profession Secondary;
|
||||
[FieldOffset(0x0014)]
|
||||
public readonly uint HeroFileId;
|
||||
[FieldOffset(0x0018)]
|
||||
public readonly uint ModelFileId;
|
||||
[FieldOffset(0x0050)]
|
||||
public readonly Array20Char Name;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[GWCAEquivalent("InstanceType")]
|
||||
public enum InstanceType
|
||||
{
|
||||
Outpost,
|
||||
Explorable,
|
||||
Loading
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
public readonly unsafe struct InstanceInfoContext
|
||||
{
|
||||
[FieldOffset(0x0004)]
|
||||
public readonly InstanceType InstanceType;
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly AreaInfo* CurrentMapInfo;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[GWCAEquivalent("AreaInfo")]
|
||||
public readonly struct AreaInfo
|
||||
{
|
||||
public readonly uint Campaign;
|
||||
public readonly uint Continent;
|
||||
public readonly uint Region;
|
||||
public readonly uint RegionType;
|
||||
public readonly uint Flags;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[GWCAEquivalent("Inventory")]
|
||||
public readonly unsafe struct Inventory
|
||||
{
|
||||
public readonly Bag* UnusedBag;
|
||||
public readonly Bag* Backpack;
|
||||
public readonly Bag* BeltPouch;
|
||||
public readonly Bag* Bag1;
|
||||
public readonly Bag* Bag2;
|
||||
public readonly Bag* EquipmentPack;
|
||||
public readonly Bag* MaterialStorage;
|
||||
public readonly Bag* UnclaimedItems;
|
||||
public readonly Bag* Storage1;
|
||||
public readonly Bag* Storage2;
|
||||
public readonly Bag* Storage3;
|
||||
public readonly Bag* Storage4;
|
||||
public readonly Bag* Storage5;
|
||||
public readonly Bag* Storage6;
|
||||
public readonly Bag* Storage7;
|
||||
public readonly Bag* Storage8;
|
||||
public readonly Bag* Storage9;
|
||||
public readonly Bag* Storage10;
|
||||
public readonly Bag* Storage11;
|
||||
public readonly Bag* Storage12;
|
||||
public readonly Bag* Storage13;
|
||||
public readonly Bag* Storage14;
|
||||
public readonly Bag* EquippedItems;
|
||||
public readonly Item* Bundle;
|
||||
public readonly uint StoragePanesUnlocked;
|
||||
|
||||
public readonly Bag*[] Bags => [
|
||||
this.Backpack,
|
||||
this.BeltPouch,
|
||||
this.Bag1,
|
||||
this.Bag2,
|
||||
this.EquipmentPack,
|
||||
this.MaterialStorage,
|
||||
this.UnclaimedItems,
|
||||
this.Storage1,
|
||||
this.Storage2,
|
||||
this.Storage3,
|
||||
this.Storage4,
|
||||
this.Storage5,
|
||||
this.Storage6,
|
||||
this.Storage7,
|
||||
this.Storage8,
|
||||
this.Storage9,
|
||||
this.Storage10,
|
||||
this.Storage11,
|
||||
this.Storage12,
|
||||
this.Storage13,
|
||||
this.Storage14,
|
||||
this.EquippedItems
|
||||
];
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
public enum ItemType : byte
|
||||
{
|
||||
Salvage,
|
||||
Axe = 2,
|
||||
Bag,
|
||||
Boots,
|
||||
Bow,
|
||||
Bundle,
|
||||
Chestpiece,
|
||||
Rune_Mod,
|
||||
Usable,
|
||||
Dye,
|
||||
Materials_Zcoins,
|
||||
Offhand,
|
||||
Gloves,
|
||||
Hammer = 15,
|
||||
Headpiece,
|
||||
CC_Shards,
|
||||
Key,
|
||||
Leggings,
|
||||
Gold_Coin,
|
||||
Quest_Item,
|
||||
Wand,
|
||||
Shield = 24,
|
||||
Staff = 26,
|
||||
Sword,
|
||||
Kit = 29,
|
||||
Trophy,
|
||||
Scroll,
|
||||
Daggers,
|
||||
Present,
|
||||
Minipet,
|
||||
Scythe,
|
||||
Spear,
|
||||
Storybook = 43,
|
||||
Costume,
|
||||
Costume_Headpiece,
|
||||
Unknown = 0xff
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[GWCAEquivalent("ItemModifier")]
|
||||
public readonly struct ItemModifier(uint mod)
|
||||
{
|
||||
public static readonly ItemModifier Zero = new();
|
||||
|
||||
public readonly uint Mod = mod;
|
||||
|
||||
public uint Identifier => this.Mod >> 16;
|
||||
public uint Arg1 => (this.Mod & 0x0000FF00) >> 8;
|
||||
public uint Arg2 => this.Mod & 0x000000FF;
|
||||
public uint Arg => this.Mod & 0x0000FFFF;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
[GWCAEquivalent("Item")]
|
||||
public readonly unsafe struct Item
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly uint ItemId;
|
||||
|
||||
[FieldOffset(0x0004)]
|
||||
public readonly uint AgentId;
|
||||
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly Bag* BagEquipped;
|
||||
|
||||
[FieldOffset(0x000C)]
|
||||
public readonly Bag* Bag;
|
||||
|
||||
[FieldOffset(0x0010)]
|
||||
public readonly ItemModifier* Modifiers;
|
||||
|
||||
[FieldOffset(0x0014)]
|
||||
public readonly uint ModifiersCount;
|
||||
|
||||
[FieldOffset(0x001C)]
|
||||
public readonly uint ModelFileId;
|
||||
|
||||
[FieldOffset(0x0020)]
|
||||
public readonly ItemType Type;
|
||||
|
||||
[FieldOffset(0x0024)]
|
||||
public readonly ushort Value;
|
||||
|
||||
[FieldOffset(0x0028)]
|
||||
public readonly uint Interaction;
|
||||
|
||||
[FieldOffset(0x002C)]
|
||||
public readonly uint ModelId;
|
||||
|
||||
[FieldOffset(0x0030)]
|
||||
public readonly char* InfoString;
|
||||
|
||||
[FieldOffset(0x0034)]
|
||||
public readonly char* NameEncoded;
|
||||
|
||||
[FieldOffset(0x0038)]
|
||||
public readonly char* CompleteNameEncoded;
|
||||
|
||||
[FieldOffset(0x003C)]
|
||||
public readonly char* SingleItemName;
|
||||
|
||||
[FieldOffset(0x0048)]
|
||||
public readonly ushort ItemFormula;
|
||||
|
||||
[FieldOffset(0x004A)]
|
||||
public readonly byte IsMaterialSalvageable;
|
||||
|
||||
[FieldOffset(0x004C)]
|
||||
public readonly ushort Quantity;
|
||||
|
||||
[FieldOffset(0x004E)]
|
||||
public readonly byte Equipped;
|
||||
|
||||
[FieldOffset(0x004F)]
|
||||
public readonly byte Profession;
|
||||
|
||||
[FieldOffset(0x0050)]
|
||||
public readonly uint Slot;
|
||||
|
||||
public readonly bool Stackable => (this.Interaction & 0x80000) != 0;
|
||||
|
||||
public readonly bool Inscribable => (this.Interaction & 0x08000000) != 0;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
[GWCAEquivalent("ItemContext")]
|
||||
public readonly struct ItemContext
|
||||
{
|
||||
[FieldOffset(0x0024)]
|
||||
public readonly GuildWarsArray<WrappedPointer<Bag>> Bags;
|
||||
|
||||
[FieldOffset(0x00B8)]
|
||||
public readonly GuildWarsArray<WrappedPointer<Item>> Items;
|
||||
|
||||
[FieldOffset(0x00F8)]
|
||||
public readonly WrappedPointer<Inventory> Inventory;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[GWCAEquivalent("Language")]
|
||||
public enum Language
|
||||
{
|
||||
English,
|
||||
Korean,
|
||||
French,
|
||||
German,
|
||||
Italian,
|
||||
Spanish,
|
||||
TraditionalChinese,
|
||||
Japanese = 8,
|
||||
Polish,
|
||||
Russian,
|
||||
BorkBorkBork = 17,
|
||||
Unknown = 0xff
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
[GWCAEquivalent("MapContext")]
|
||||
public readonly struct MapContext
|
||||
{
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
[GWCAEquivalent("NPC")]
|
||||
public readonly unsafe struct NpcContext
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly uint ModelId;
|
||||
|
||||
[FieldOffset(0x000C)]
|
||||
public readonly uint Sex;
|
||||
|
||||
[FieldOffset(0x0010)]
|
||||
public readonly NpcFlags Flags;
|
||||
|
||||
[FieldOffset(0x0014)]
|
||||
public readonly uint Primary;
|
||||
|
||||
[FieldOffset(0x001C)]
|
||||
public readonly byte DefaultLevel;
|
||||
|
||||
[FieldOffset(0x0020)]
|
||||
public readonly char* EncName;
|
||||
|
||||
[FieldOffset(0x0028)]
|
||||
public readonly int FilesCount;
|
||||
|
||||
[FieldOffset(0x002C)]
|
||||
public readonly int FilesCapacity;
|
||||
|
||||
[Flags]
|
||||
public enum NpcFlags : uint
|
||||
{
|
||||
None = 0x0000,
|
||||
Henchman = 0x0010,
|
||||
Hero = 0x0020,
|
||||
Spirit = 0x4000,
|
||||
Minion = 0x0100,
|
||||
Pet = 0x000D
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[GWCAEquivalent("PetInfo")]
|
||||
public readonly unsafe struct PetContext
|
||||
{
|
||||
public readonly uint AgentId;
|
||||
public readonly uint OwnerAgentId;
|
||||
public readonly char* PetName;
|
||||
public readonly uint ModelFileId1;
|
||||
public readonly uint ModelFileId2;
|
||||
public readonly Behavior Behavior;
|
||||
public readonly uint LockedTargetId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public readonly struct ControlledMinion
|
||||
{
|
||||
public readonly uint AgentId;
|
||||
public readonly uint MinionCount;
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
using System.Extensions;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[Flags]
|
||||
public enum PlayerPartyMemberState : uint
|
||||
{
|
||||
None = 0,
|
||||
Connected = 1,
|
||||
Ticked = 2
|
||||
}
|
||||
|
||||
public enum PartySearchType
|
||||
{
|
||||
PartySearchType_Hunting = 0,
|
||||
PartySearchType_Mission = 1,
|
||||
PartySearchType_Quest = 2,
|
||||
PartySearchType_Trade = 3,
|
||||
PartySearchType_Guild = 4,
|
||||
};
|
||||
|
||||
[Flags]
|
||||
public enum PartyFlags : uint
|
||||
{
|
||||
None = 0,
|
||||
HardMode = 0x10, // Bit 4
|
||||
Defeated = 0x20, // Bit 5
|
||||
PartyLeader = 0x80 // Bit 7 (0x7th position)
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0xC)]
|
||||
public readonly unsafe struct PartyMoraleContext
|
||||
{
|
||||
[FieldOffset(0x000C)]
|
||||
public readonly PartyMemberMoraleInfo* MoraleInfo;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
public readonly struct PartyMemberMoraleInfo
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly uint AgentId;
|
||||
[FieldOffset(0x0014)]
|
||||
public readonly uint Morale;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x58)]
|
||||
[GWCAEquivalent("PartyContext")]
|
||||
public readonly unsafe struct PartyContext
|
||||
{
|
||||
[FieldOffset(0x0014)]
|
||||
public readonly PartyFlags Flags;
|
||||
[FieldOffset(0x0040)]
|
||||
public readonly GuildWarsArray<WrappedPointer<PartyInfo>> Parties;
|
||||
[FieldOffset(0x0054)]
|
||||
public readonly PartyInfo* PlayerParty;
|
||||
[FieldOffset(0x00C0)]
|
||||
public readonly GuildWarsArray<WrappedPointer<PartySearch>> PartySearches;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0xC)]
|
||||
public readonly struct PlayerPartyMember
|
||||
{
|
||||
public readonly uint LogingNumber;
|
||||
public readonly uint CalledTargetId;
|
||||
public readonly PlayerPartyMemberState State;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x18)]
|
||||
public readonly struct HeroPartyMember
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly uint AgentId;
|
||||
[FieldOffset(0x0004)]
|
||||
public readonly uint OwnerPlayerId;
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly uint HeroId;
|
||||
[FieldOffset(0x0014)]
|
||||
public readonly uint Level;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x34)]
|
||||
public readonly struct HenchmanPartyMember
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly uint AgentId;
|
||||
[FieldOffset(0x002C)]
|
||||
public readonly Profession Profession;
|
||||
[FieldOffset(0x0030)]
|
||||
public readonly uint Level;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x84)]
|
||||
[GWCAEquivalent("PartyInfo")]
|
||||
public readonly struct PartyInfo
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly uint PartyId;
|
||||
[FieldOffset(0x0004)]
|
||||
public readonly GuildWarsArray<PlayerPartyMember> Players;
|
||||
[FieldOffset(0x0014)]
|
||||
public readonly GuildWarsArray<HenchmanPartyMember> Henchmen;
|
||||
[FieldOffset(0x0024)]
|
||||
public readonly GuildWarsArray<HeroPartyMember> Heroes;
|
||||
[FieldOffset(0x0034)]
|
||||
public readonly GuildWarsArray<uint> Others;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[GWCAEquivalent("PartySearch")]
|
||||
public readonly struct PartySearch
|
||||
{
|
||||
public readonly uint PartySearchId;
|
||||
public readonly PartySearchType PartySearchType;
|
||||
public readonly uint HardMode;
|
||||
public readonly uint District;
|
||||
public readonly uint Language;
|
||||
public readonly uint PartySize;
|
||||
public readonly uint HeroCount;
|
||||
public readonly Array32Char Message;
|
||||
public readonly Array20Char PartyLeader;
|
||||
public readonly Profession Primary;
|
||||
public readonly Profession Secondary;
|
||||
public readonly uint Level;
|
||||
public readonly uint Timestamp;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x34)]
|
||||
public unsafe struct PartySearchWindowContext
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public uint* Vtable;
|
||||
[FieldOffset(0x0004)]
|
||||
public uint FrameId;
|
||||
[FieldOffset(0x0020)]
|
||||
public uint SelectedPartySearchId;
|
||||
[FieldOffset(0x0024)]
|
||||
public uint SelectedHeroId;
|
||||
[FieldOffset(0x0028)]
|
||||
public uint SelectedHenchmanId;
|
||||
[FieldOffset(0x002C)]
|
||||
public uint CurrentTab;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[Flags]
|
||||
public enum PlayerContextFlags : uint
|
||||
{
|
||||
None = 0,
|
||||
PvP = 0x800
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x50)]
|
||||
[GWCAEquivalent("PlayerContext")]
|
||||
public readonly unsafe struct PlayerContext
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly int AgentId;
|
||||
|
||||
[FieldOffset(0x0014)]
|
||||
public readonly PlayerContextFlags Flags;
|
||||
|
||||
[FieldOffset(0x0018)]
|
||||
public readonly uint PrimaryProfession;
|
||||
|
||||
[FieldOffset(0x001C)]
|
||||
public readonly uint SecondaryProfession;
|
||||
|
||||
[FieldOffset(0x0024)]
|
||||
public readonly char* NameEncoded;
|
||||
|
||||
[FieldOffset(0x0028)]
|
||||
public readonly char* Name;
|
||||
|
||||
[FieldOffset(0x002C)]
|
||||
public readonly uint PartyLeaderPlayerNumber;
|
||||
|
||||
[FieldOffset(0x0030)]
|
||||
public readonly uint ActiveTitleTier;
|
||||
|
||||
[FieldOffset(0x0034)]
|
||||
public readonly uint ReforgedOrDhuumsFlags;
|
||||
|
||||
[FieldOffset(0x0038)]
|
||||
public readonly uint PlayerNumber;
|
||||
|
||||
[FieldOffset(0x003C)]
|
||||
public readonly uint PartySize;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
public readonly struct PlayerControlledCharContext
|
||||
{
|
||||
[FieldOffset(0x0014)]
|
||||
public readonly uint AgentId;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using System.Extensions;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
[GWCAEquivalent("PreGameContext")]
|
||||
public readonly struct PreGameContext
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly uint FrameId;
|
||||
|
||||
[FieldOffset(0x0124)]
|
||||
public readonly uint ChosenCharacterIndex;
|
||||
|
||||
[FieldOffset(0x0148)]
|
||||
public readonly GuildWarsArray<LoginCharacterContext> LoginCharacters;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
public readonly struct LoginCharacterContext
|
||||
{
|
||||
[FieldOffset(0x0004)]
|
||||
public readonly Array20Char CharacterName;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[GWCAEquivalent("EnumPreference")]
|
||||
public enum EnumPreference : uint
|
||||
{
|
||||
CharSortOrder = 0,
|
||||
AntiAliasing = 1,
|
||||
Reflections = 2,
|
||||
ShaderQuality = 3,
|
||||
ShadowQuality = 4,
|
||||
TerrainQuality = 5,
|
||||
InterfaceSize = 6,
|
||||
FrameLimiter = 7,
|
||||
Count = 8
|
||||
}
|
||||
|
||||
[GWCAEquivalent("CharSortOrder")]
|
||||
public enum CharSortOrder : uint
|
||||
{
|
||||
None = 0,
|
||||
Alphabetize = 1,
|
||||
PvPRP = 2
|
||||
}
|
||||
|
||||
[GWCAEquivalent("NumberPreference")]
|
||||
public enum NumberPreference : uint
|
||||
{
|
||||
AutoTournPartySort = 0,
|
||||
ChatState = 1,
|
||||
Count = 0x2b
|
||||
}
|
||||
|
||||
[GWCAEquivalent("FlagPreference")]
|
||||
public enum FlagPreference : uint
|
||||
{
|
||||
}
|
||||
|
||||
[GWCAEquivalent("StringPreference")]
|
||||
public enum StringPreference : uint
|
||||
{
|
||||
Unk1 = 0,
|
||||
Unk2 = 1,
|
||||
LastCharacterName = 2,
|
||||
Count = 3
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[GWCAEquivalent("Profession")]
|
||||
public enum Profession : uint
|
||||
{
|
||||
None,
|
||||
Warrior,
|
||||
Ranger,
|
||||
Monk,
|
||||
Necromancer,
|
||||
Mesmer,
|
||||
Elementalist,
|
||||
Assassin,
|
||||
Ritualist,
|
||||
Paragon,
|
||||
Dervish
|
||||
}
|
||||
|
||||
public enum ProfessionByte : byte
|
||||
{
|
||||
None,
|
||||
Warrior,
|
||||
Ranger,
|
||||
Monk,
|
||||
Necromancer,
|
||||
Mesmer,
|
||||
Elementalist,
|
||||
Assassin,
|
||||
Ritualist,
|
||||
Paragon,
|
||||
Dervish
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x0014)]
|
||||
public readonly struct ProfessionsContext
|
||||
{
|
||||
public readonly uint AgentId;
|
||||
public readonly Profession CurrentPrimary;
|
||||
public readonly Profession CurrentSecondary;
|
||||
public readonly uint UnlockedProfessionsFlags;
|
||||
|
||||
public bool ProfessionUnlocked(int professionId)
|
||||
{
|
||||
return (this.UnlockedProfessionsFlags & (1U << professionId)) != 0;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x0034)]
|
||||
[GWCAEquivalent("Quest")]
|
||||
public readonly struct QuestContext
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly uint QuestId;
|
||||
|
||||
[FieldOffset(0x0014)]
|
||||
public readonly uint MapFrom;
|
||||
|
||||
[FieldOffset(0x0018)]
|
||||
public readonly Vector3 Marker;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0xC)]
|
||||
public readonly unsafe struct MissionObjectiveContext
|
||||
{
|
||||
public readonly uint ObjectiveId;
|
||||
public readonly char* EncodedString;
|
||||
public readonly uint Type;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[GWCAEquivalent("ServerRegion")]
|
||||
public enum ServerRegion
|
||||
{
|
||||
International = -2,
|
||||
America = 0,
|
||||
Korea,
|
||||
Europe,
|
||||
China,
|
||||
Japan,
|
||||
Unknown = 0xff
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[GWCAEquivalent("SkillbarSkill")]
|
||||
public readonly struct SkillContext
|
||||
{
|
||||
public readonly uint Adrenaline1;
|
||||
public readonly uint Adrenaline2;
|
||||
public readonly uint Recharge;
|
||||
public readonly uint Id;
|
||||
public readonly uint Event;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0xBC)]
|
||||
[GWCAEquivalent("Skillbar")]
|
||||
public readonly struct SkillbarContext
|
||||
{
|
||||
public readonly uint AgentId;
|
||||
public readonly SkillContext Skill0;
|
||||
public readonly SkillContext Skill1;
|
||||
public readonly SkillContext Skill2;
|
||||
public readonly SkillContext Skill3;
|
||||
public readonly SkillContext Skill4;
|
||||
public readonly SkillContext Skill5;
|
||||
public readonly SkillContext Skill6;
|
||||
public readonly SkillContext Skill7;
|
||||
public readonly uint Disabled;
|
||||
public readonly uint Casting;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x10)]
|
||||
[GWCAEquivalent("Buff")]
|
||||
public readonly struct Buff
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly uint SkillId;
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly uint BuffId;
|
||||
[FieldOffset(0x000C)]
|
||||
public readonly uint TargetAgentId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x18)]
|
||||
[GWCAEquivalent("Effect")]
|
||||
public readonly struct Effect
|
||||
{
|
||||
public readonly uint SkillId;
|
||||
public readonly uint AttributeLevel;
|
||||
public readonly uint EffectId;
|
||||
public readonly uint AgentId;
|
||||
public readonly float Duration;
|
||||
public readonly uint Timestamp;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public readonly struct DupeSkill
|
||||
{
|
||||
public readonly uint SkillId;
|
||||
public readonly uint Count;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System.Extensions;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[GWCAEquivalent("SkillTemplate")]
|
||||
public readonly struct SkillTemplate(uint primary, uint secondary, uint attributeCount, Array12Uint attributeIds, Array12Uint attributeValues, Array8Uint skills)
|
||||
{
|
||||
public readonly uint Primary = primary;
|
||||
public readonly uint Secondary = secondary;
|
||||
public readonly uint AttributesCount = attributeCount;
|
||||
public readonly Array12Uint AttributeIds = attributeIds;
|
||||
public readonly Array12Uint AttributeValues = attributeValues;
|
||||
public readonly Array8Uint Skills = skills;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[GWCAEquivalent("TagInfo")]
|
||||
public readonly struct TagInfo
|
||||
{
|
||||
public readonly ushort GuildId;
|
||||
public readonly byte Primary;
|
||||
public readonly byte Secondary;
|
||||
public readonly ushort Level;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
[GWCAEquivalent("TextParser")]
|
||||
public struct TextParserContext
|
||||
{
|
||||
[FieldOffset(0x01D0)]
|
||||
public Language Language;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[Flags]
|
||||
public enum TitleProps : uint
|
||||
{
|
||||
None = 0,
|
||||
PercentageBased = 1,
|
||||
HasTiers = 2
|
||||
// Note: The HasTiers check uses (props & 3) == 2, which means bit 1 is set but bit 0 is not
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x2C)]
|
||||
[GWCAEquivalent("Title")]
|
||||
public readonly struct TitleContext
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly TitleProps Props;
|
||||
[FieldOffset(0x0004)]
|
||||
public readonly uint CurrentPoints;
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly uint CurrentTitleTierIndex;
|
||||
[FieldOffset(0x000C)]
|
||||
public readonly uint PointsNeededForCurrentRank;
|
||||
[FieldOffset(0x0014)]
|
||||
public readonly uint NextTitleTierIndex;
|
||||
[FieldOffset(0x0018)]
|
||||
public readonly uint PointsNeededForNextRank;
|
||||
[FieldOffset(0x001C)]
|
||||
public readonly uint MaxTitleRank;
|
||||
[FieldOffset(0x0020)]
|
||||
public readonly uint MaxTitleTierIndex;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0xC)]
|
||||
[GWCAEquivalent("TitleTier")]
|
||||
public readonly unsafe struct TitleTier
|
||||
{
|
||||
public readonly TitleProps Props;
|
||||
public readonly uint TierNumber;
|
||||
public readonly char* TierNameEncoded;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[GWCAEquivalent("TitleClientData")]
|
||||
public readonly struct TitleClientData
|
||||
{
|
||||
public readonly uint TitleId;
|
||||
public readonly uint NameId;
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Interop.GuildWars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
[GWCAEquivalent("WorldContext")]
|
||||
public readonly unsafe struct WorldContext
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly AccountInfoContext* AccountInfo;
|
||||
|
||||
[FieldOffset(0x0024)]
|
||||
public readonly GuildWarsArray<uint> MerchItems;
|
||||
|
||||
[FieldOffset(0x0034)]
|
||||
public readonly GuildWarsArray<uint> MerchItems2;
|
||||
|
||||
[FieldOffset(0x007C)]
|
||||
public readonly GuildWarsArray<MapAgentContext> MapAgents;
|
||||
|
||||
[FieldOffset(0x009C)]
|
||||
public readonly Vector3 AllFlag;
|
||||
|
||||
[FieldOffset(0x00AC)]
|
||||
public readonly GuildWarsArray<PartyAttribute> Attributes;
|
||||
|
||||
[FieldOffset(0x0508)]
|
||||
public readonly GuildWarsArray<AgentEffects> PartyEffects;
|
||||
|
||||
[FieldOffset(0x0528)]
|
||||
public readonly uint ActiveQuestId;
|
||||
|
||||
[FieldOffset(0x052C)]
|
||||
public readonly GuildWarsArray<QuestContext> QuestLog;
|
||||
|
||||
[FieldOffset(0x0564)]
|
||||
public readonly GuildWarsArray<MissionObjectiveContext> MissionObjectives;
|
||||
|
||||
[FieldOffset(0x0574)]
|
||||
public readonly GuildWarsArray<uint> HenchmenAgentIds;
|
||||
|
||||
[FieldOffset(0x0584)]
|
||||
public readonly GuildWarsArray<HeroFlag> HeroFlags;
|
||||
|
||||
[FieldOffset(0x0594)]
|
||||
public readonly GuildWarsArray<HeroInfo> HeroInfos;
|
||||
|
||||
[FieldOffset(0x05A4)]
|
||||
public readonly GuildWarsArray<nuint> CartographedAreas;
|
||||
|
||||
[FieldOffset(0x05BC)]
|
||||
public readonly GuildWarsArray<ControlledMinion> ControlledMinions;
|
||||
|
||||
[FieldOffset(0x05CC)]
|
||||
public readonly GuildWarsArray<uint> MissionsCompleted;
|
||||
|
||||
[FieldOffset(0x05DC)]
|
||||
public readonly GuildWarsArray<uint> MissionsBonus;
|
||||
|
||||
[FieldOffset(0x05EC)]
|
||||
public readonly GuildWarsArray<uint> MissionsCompletedHardMode;
|
||||
|
||||
[FieldOffset(0x05FC)]
|
||||
public readonly GuildWarsArray<uint> MissionsBonusHardMode;
|
||||
|
||||
[FieldOffset(0x060C)]
|
||||
public readonly GuildWarsArray<uint> UnlockedMap;
|
||||
|
||||
[FieldOffset(0x062C)]
|
||||
public readonly GuildWarsArray<PartyMoraleContext> PartyMorale;
|
||||
|
||||
[FieldOffset(0x067C)]
|
||||
public readonly uint PlayerNumber;
|
||||
|
||||
[FieldOffset(0x0680)]
|
||||
public readonly PlayerControlledCharContext* PlayerControlledChar;
|
||||
|
||||
[FieldOffset(0x0684)]
|
||||
public readonly uint HardModeUnlocked;
|
||||
|
||||
[FieldOffset(0x06AC)]
|
||||
public readonly GuildWarsArray<PetContext> Pets;
|
||||
|
||||
[FieldOffset(0x06BC)]
|
||||
public readonly GuildWarsArray<ProfessionsContext> Professions;
|
||||
|
||||
[FieldOffset(0x06F0)]
|
||||
public readonly GuildWarsArray<SkillbarContext> Skillbars;
|
||||
|
||||
[FieldOffset(0x0700)]
|
||||
public readonly GuildWarsArray<uint> LearnableCharacterSkills;
|
||||
|
||||
[FieldOffset(0x0710)]
|
||||
public readonly GuildWarsArray<uint> UnlockedCharacterSkills;
|
||||
|
||||
[FieldOffset(0x0720)]
|
||||
public readonly GuildWarsArray<DupeSkill> DupeSkills;
|
||||
|
||||
[FieldOffset(0x0740)]
|
||||
public readonly uint Experience;
|
||||
|
||||
[FieldOffset(0x0748)]
|
||||
public readonly uint CurrentKurzick;
|
||||
|
||||
[FieldOffset(0x0750)]
|
||||
public readonly uint TotalKurzick;
|
||||
|
||||
[FieldOffset(0x0758)]
|
||||
public readonly uint CurrentLuxon;
|
||||
|
||||
[FieldOffset(0x0760)]
|
||||
public readonly uint TotalLuxon;
|
||||
|
||||
[FieldOffset(0x0768)]
|
||||
public readonly uint CurrentImperial;
|
||||
|
||||
[FieldOffset(0x0770)]
|
||||
public readonly uint TotalImperial;
|
||||
|
||||
[FieldOffset(0x0788)]
|
||||
public readonly uint Level;
|
||||
|
||||
[FieldOffset(0x0790)]
|
||||
public readonly uint Morale;
|
||||
|
||||
[FieldOffset(0x0798)]
|
||||
public readonly uint CurrentBalthazar;
|
||||
|
||||
[FieldOffset(0x07A0)]
|
||||
public readonly uint TotalBalthazar;
|
||||
|
||||
[FieldOffset(0x07A8)]
|
||||
public readonly uint CurrentSkillPoints;
|
||||
|
||||
[FieldOffset(0x07B0)]
|
||||
public readonly uint TotalSkillPoints;
|
||||
|
||||
[FieldOffset(0x07B8)]
|
||||
public readonly uint MaxKurzick;
|
||||
|
||||
[FieldOffset(0x07BC)]
|
||||
public readonly uint MaxLuxon;
|
||||
|
||||
[FieldOffset(0x07C0)]
|
||||
public readonly uint MaxBalthazar;
|
||||
|
||||
[FieldOffset(0x07C4)]
|
||||
public readonly uint MaxImperial;
|
||||
|
||||
[FieldOffset(0x07CC)]
|
||||
public readonly GuildWarsArray<AgentInfo> AgentInfos;
|
||||
|
||||
[FieldOffset(0x07FC)]
|
||||
public readonly GuildWarsArray<NpcContext> Npcs;
|
||||
|
||||
[FieldOffset(0x080C)]
|
||||
public readonly GuildWarsArray<PlayerContext> Players;
|
||||
|
||||
[FieldOffset(0x081C)]
|
||||
public readonly GuildWarsArray<TitleContext> Titles;
|
||||
|
||||
[FieldOffset(0x082C)]
|
||||
public readonly GuildWarsArray<TitleTier> TitleTiers;
|
||||
|
||||
[FieldOffset(0x083C)]
|
||||
public readonly GuildWarsArray<uint> VanquishedAreas;
|
||||
|
||||
[FieldOffset(0x084C)]
|
||||
public readonly uint FoesKilled;
|
||||
|
||||
[FieldOffset(0x0850)]
|
||||
public readonly uint FoesToKill;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Daybreak.API.Interop;
|
||||
|
||||
public interface IHook<T>
|
||||
: IDisposable where T : Delegate
|
||||
{
|
||||
public T Continue { get; }
|
||||
|
||||
public nuint ContinueAddress { get; }
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
using Daybreak.API.Converters;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Daybreak.API.Interop;
|
||||
|
||||
[JsonConverter(typeof(PointerValueConverter))]
|
||||
public readonly struct PointerValue(nuint address) : IEquatable<PointerValue>, IEquatable<nuint>, IEquatable<nint>
|
||||
{
|
||||
public readonly nuint Address = address;
|
||||
|
||||
public bool Equals(PointerValue other)
|
||||
{
|
||||
return this.Address.Equals(other.Address);
|
||||
}
|
||||
|
||||
public bool Equals(nuint other)
|
||||
{
|
||||
return this.Address.Equals(other);
|
||||
}
|
||||
|
||||
public bool Equals(nint other)
|
||||
{
|
||||
return this.Address.Equals((nuint)other);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"0x{this.Address:X8}";
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj) => obj is PointerValue value && this.Equals(value);
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(this.Address);
|
||||
}
|
||||
|
||||
public static bool operator ==(PointerValue left, PointerValue right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
public static bool operator !=(PointerValue left, PointerValue right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
public static implicit operator PointerValue(nuint address)
|
||||
{
|
||||
return new PointerValue(address);
|
||||
}
|
||||
|
||||
public static implicit operator PointerValue(nint address)
|
||||
{
|
||||
return new PointerValue((nuint)address);
|
||||
}
|
||||
|
||||
public static implicit operator PointerValue(int address)
|
||||
{
|
||||
return new PointerValue((nuint)address);
|
||||
}
|
||||
|
||||
public static implicit operator PointerValue(uint address)
|
||||
{
|
||||
return new PointerValue(address);
|
||||
}
|
||||
|
||||
public static PointerValue Parse(string s)
|
||||
{
|
||||
if (s.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase)
|
||||
&& nuint.TryParse(s.AsSpan(2), System.Globalization.NumberStyles.HexNumber, null, out var v))
|
||||
{
|
||||
return new PointerValue(v);
|
||||
}
|
||||
|
||||
throw new FormatException($"Invalid pointer format: {s}");
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using Daybreak.API.Interop;
|
||||
|
||||
namespace Daybreak.API.Models;
|
||||
|
||||
public sealed class AddressState
|
||||
{
|
||||
public required string Name { get; init; }
|
||||
public required PointerValue Address { get; init; }
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using System.Core.Extensions;
|
||||
using System.Extensions;
|
||||
|
||||
namespace Daybreak.API.Models;
|
||||
|
||||
public sealed class AsyncRefreshCache<T>(TimeSpan refreshRate, Func<CancellationToken, ValueTask<T>> refreshFunc)
|
||||
{
|
||||
private readonly Func<CancellationToken, ValueTask<T>> refreshFunc = refreshFunc.ThrowIfNull();
|
||||
|
||||
private readonly SemaphoreSlim semaphoreSlim = new(1);
|
||||
|
||||
private T? cache;
|
||||
private DateTime lastUpdateDateTime = DateTime.MinValue;
|
||||
private TimeSpan refreshRate = refreshRate;
|
||||
|
||||
public async ValueTask<T> GetAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (this.cache is not null && DateTime.UtcNow - this.lastUpdateDateTime < this.refreshRate)
|
||||
{
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
using var ctx = await this.semaphoreSlim.Acquire(cancellationToken);
|
||||
if (DateTime.UtcNow - this.lastUpdateDateTime > this.refreshRate ||
|
||||
this.cache is null)
|
||||
{
|
||||
this.lastUpdateDateTime = DateTime.UtcNow;
|
||||
this.cache = await this.refreshFunc(cancellationToken);
|
||||
}
|
||||
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
public void UpdateRefreshRate(TimeSpan newRefreshRate)
|
||||
{
|
||||
this.refreshRate = newRefreshRate;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using Daybreak.API.Interop;
|
||||
|
||||
namespace Daybreak.API.Models;
|
||||
|
||||
[GWCAEquivalent("Channel")]
|
||||
public enum Channel : uint
|
||||
{
|
||||
Alliance = 0,
|
||||
Allies = 1, // coop with two groups for instance.
|
||||
GWCA1 = 2,
|
||||
All = 3,
|
||||
GWCA2 = 4,
|
||||
Moderator = 5,
|
||||
Emote = 6,
|
||||
Warning = 7, // shows in the middle of the screen and does not parse <c> tags
|
||||
GWCA3 = 8,
|
||||
Guild = 9,
|
||||
Global = 10,
|
||||
Group = 11,
|
||||
Trade = 12,
|
||||
Advisory = 13,
|
||||
Whisper = 14,
|
||||
Count,
|
||||
|
||||
// non-standard channel, but useful.
|
||||
Command
|
||||
};
|
||||
@@ -1,12 +0,0 @@
|
||||
using Daybreak.API.Interop;
|
||||
|
||||
namespace Daybreak.API.Models;
|
||||
|
||||
public sealed class HookState
|
||||
{
|
||||
public required bool Hooked { get; init; }
|
||||
public required string Name { get; init; }
|
||||
public required PointerValue TargetAddress { get; init; }
|
||||
public required PointerValue ContinueAddress { get; init; }
|
||||
public required PointerValue DetourAddress { get; init; }
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using Daybreak.API.Interop;
|
||||
|
||||
namespace Daybreak.API.Models;
|
||||
|
||||
[GWCAEquivalent("UIMessage")]
|
||||
public enum UIMessage : uint
|
||||
{
|
||||
None = 0x0,
|
||||
InitFrame = 0x9,
|
||||
DestroyFrame = 0xb,
|
||||
KeyDown = 0x20, // wparam = UIPacket::kKeyAction*
|
||||
KeyUp = 0x22, // wparam = UIPacket::kKeyAction*
|
||||
MouseClick = 0x24, // wparam = UIPacket::kMouseClick*
|
||||
MouseClick2 = 0x31, // wparam = UIPacket::kMouseAction*
|
||||
MouseAction = 0x32, // wparam = UIPacket::kMouseAction*
|
||||
FrameMessage_QuerySelectedIndex = 0x59, // Used to query selected index in character selector
|
||||
WriteToChatLog = 0x10000000 | 0x7F, // wparam = UIPacket::kWriteToChatLog*. Triggered by the game when it wants to add a new message to chat.
|
||||
WriteToChatLogWithSender = 0x10000000 | 0x80, // wparam = UIPacket::kWriteToChatLogWithSender*. Triggered by the game when it wants to add a new message to chat.
|
||||
CheckUIState = 0x10000000 | 0x118, // lparam = uint32_t* out state (2 = char select ready)
|
||||
Logout = 0x10000000 | 0x9D, // wparam = { bool unknown, bool character_select }
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.API.Models;
|
||||
|
||||
public static class UIPackets
|
||||
{
|
||||
public enum MouseButtons
|
||||
{
|
||||
Left = 0x0,
|
||||
Middle = 0x1,
|
||||
Right = 0x2
|
||||
}
|
||||
|
||||
public enum ActionState
|
||||
{
|
||||
MouseDown = 0x6,
|
||||
MouseUp = 0x7,
|
||||
MouseClick = 0x8,
|
||||
MouseDoubleClick = 0x9,
|
||||
DragRelease = 0xb,
|
||||
KeyDown = 0xe
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public readonly struct LogChatMessage(string message, Channel channel)
|
||||
{
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public readonly string Message = message;
|
||||
public readonly Channel Channel = channel;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public readonly struct UIChatMessage(Channel channel, string message, Channel channel2)
|
||||
{
|
||||
public readonly Channel Channel = channel;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public readonly string Message = message;
|
||||
public readonly Channel Channel2 = channel2;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public readonly struct KeyAction(uint key, uint wParam = 0x4000, uint lParam = 0x0006)
|
||||
{
|
||||
public readonly uint Key = key;
|
||||
public readonly uint WParam = wParam;
|
||||
public readonly uint LParam = lParam;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public readonly struct MouseClick(MouseButtons mouseButton, uint isDoubleClick, uint unknownTypeScreenPos)
|
||||
{
|
||||
public readonly MouseButtons MouseButton = mouseButton;
|
||||
public readonly uint IsDoubleClick = isDoubleClick;
|
||||
public readonly uint UnknownTypeScreenPos = unknownTypeScreenPos;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public readonly struct MouseAction(uint frameId, uint childOffsetId, ActionState currentState, nuint wparam = 0, nuint lparam = 0)
|
||||
{
|
||||
public readonly uint FrameId = frameId;
|
||||
public readonly uint ChildOffsetId = childOffsetId;
|
||||
public readonly ActionState CurrentState = currentState;
|
||||
public readonly nuint WParam = wparam;
|
||||
public readonly nuint LParam = lparam;
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,6 @@ namespace Daybreak.API.Serialization;
|
||||
[JsonSerializable(typeof(JsonElement))]
|
||||
[JsonSerializable(typeof(HealthCheckResponse))]
|
||||
[JsonSerializable(typeof(HealthCheckEntryResponse))]
|
||||
[JsonSerializable(typeof(HookState))]
|
||||
[JsonSerializable(typeof(ArraySegment<HookState>))]
|
||||
[JsonSerializable(typeof(AddressState))]
|
||||
[JsonSerializable(typeof(ArraySegment<AddressState>))]
|
||||
[JsonSerializable(typeof(MainPlayerState))]
|
||||
[JsonSerializable(typeof(QuestLogInformation))]
|
||||
[JsonSerializable(typeof(QuestInformation))]
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
using Daybreak.API.Interop.GuildWars;
|
||||
using Daybreak.API.Extensions;
|
||||
using Daybreak.API.Interop;
|
||||
using Daybreak.API.Interop.GuildWars;
|
||||
using Daybreak.API.Models;
|
||||
using Daybreak.API.Services.Interop;
|
||||
using Daybreak.Shared.Models.Api;
|
||||
using System.Core.Extensions;
|
||||
using System.Extensions;
|
||||
using System.Extensions.Core;
|
||||
using System.Runtime.InteropServices;
|
||||
using ZLinq;
|
||||
@@ -18,13 +21,6 @@ public sealed class CharacterSelectService(
|
||||
PreferencesService preferencesService,
|
||||
ILogger<CharacterSelectService> logger)
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
private readonly struct LogOutMessage(uint unknown, uint characterSelect)
|
||||
{
|
||||
public readonly uint Unknown = unknown;
|
||||
public readonly uint CharacterSelect = characterSelect;
|
||||
}
|
||||
|
||||
private readonly InstanceContextService instanceContextService = instanceContextService.ThrowIfNull();
|
||||
private readonly PlatformContextService platformContextService = platformContextService.ThrowIfNull();
|
||||
private readonly UIContextService uiContextService = uiContextService.ThrowIfNull();
|
||||
@@ -42,7 +38,7 @@ public sealed class CharacterSelectService(
|
||||
{
|
||||
var gameContext = this.gameContextService.GetGameContext();
|
||||
if (gameContext.IsNull ||
|
||||
gameContext.Pointer->WorldContext is null)
|
||||
gameContext.Pointer->World is null)
|
||||
{
|
||||
scopedLogger.LogError("Game context is not initialized");
|
||||
return default;
|
||||
@@ -55,21 +51,20 @@ public sealed class CharacterSelectService(
|
||||
return default;
|
||||
}
|
||||
|
||||
var currentUuid = gameContext.Pointer->CharContext->PlayerUuid.ToString();
|
||||
var currentUuid = (*(Uuid*)gameContext.Pointer->Character->PlayerUuid).ToString();
|
||||
var availableChars = new List<CharacterSelectEntry>((int)availableCharsContext.Pointer->Size);
|
||||
foreach (var charContext in *availableCharsContext.Pointer)
|
||||
{
|
||||
var nameSpan = charContext.Name.AsSpan();
|
||||
var name = new string(nameSpan[..nameSpan.IndexOf('\0')]);
|
||||
var name = new string(charContext.Name);
|
||||
availableChars.Add(new CharacterSelectEntry(
|
||||
charContext.Uuid.ToString(),
|
||||
(*(Uuid*)charContext.Uuid).ToString(),
|
||||
name,
|
||||
charContext.Primary,
|
||||
charContext.Secondary,
|
||||
charContext.Campaign,
|
||||
charContext.MapId,
|
||||
charContext.Level,
|
||||
charContext.IsPvp));
|
||||
(uint)charContext.GetPrimaryProfession(),
|
||||
(uint)charContext.GetSecondaryProfession(),
|
||||
(uint)charContext.GetCampaign(),
|
||||
(uint)charContext.GetMapId(),
|
||||
(uint)charContext.GetLevel(),
|
||||
charContext.IsPvP()));
|
||||
}
|
||||
|
||||
// TODO: Reforged sometimes returns Zero UUID even when in-game, need to investigate why
|
||||
@@ -143,6 +138,26 @@ public sealed class CharacterSelectService(
|
||||
public uint Play;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
private readonly unsafe struct CharSelectorContext
|
||||
{
|
||||
[FieldOffset(0x0000)]
|
||||
public readonly uint Vtable;
|
||||
|
||||
[FieldOffset(0x0004)]
|
||||
public readonly uint FrameId;
|
||||
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly GuildWarsArray<WrappedPointer<CharSelectorChar>> Chars;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1)]
|
||||
private readonly struct CharSelectorChar
|
||||
{
|
||||
[FieldOffset(0x0020)]
|
||||
public readonly Array20Char Name;
|
||||
}
|
||||
|
||||
private async Task<bool> SelectCharacterToPlay(string characterName, bool play, CancellationToken cancellationToken)
|
||||
{
|
||||
var scopedLogger = this.logger.CreateScopedLogger();
|
||||
@@ -173,7 +188,7 @@ public sealed class CharacterSelectService(
|
||||
|
||||
// Get current selected index
|
||||
uint selectedIdx = 0;
|
||||
this.uiContextService.SendFrameUIMessage(panesFrame, UIMessage.FrameMessage_QuerySelectedIndex, null, &selectedIdx);
|
||||
this.uiContextService.SendFrameUIMessage(panesFrame, UIMessage.kFrameMessage_0x4a, null, &selectedIdx);
|
||||
|
||||
// Find target character index
|
||||
uint targetIdx = 0xFFFF;
|
||||
@@ -234,19 +249,21 @@ public sealed class CharacterSelectService(
|
||||
Play = 0
|
||||
};
|
||||
|
||||
var action = new UIPackets.MouseAction(
|
||||
selectorFrame->FrameId,
|
||||
selectorFrame->ChildOffsetId,
|
||||
UIPackets.ActionState.MouseClick,
|
||||
(nuint)(&buttonParam));
|
||||
var action = new kMouseAction
|
||||
{
|
||||
FrameId = selectorFrame->FrameId,
|
||||
ChildOffsetId = selectorFrame->ChildOffsetId,
|
||||
CurrentState = GWCA.GW.UI.UIPacket.ActionState.MouseClick,
|
||||
Wparam = (nint)(&buttonParam)
|
||||
};
|
||||
|
||||
if (!this.uiContextService.SendFrameUIMessage(parentFrame, UIMessage.MouseClick2, &action))
|
||||
if (!this.uiContextService.SendFrameUIMessage(parentFrame, UIMessage.kMouseClick2, &action))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint newSelectedIdx = 0;
|
||||
this.uiContextService.SendFrameUIMessage(panesFrame, UIMessage.FrameMessage_QuerySelectedIndex, null, &newSelectedIdx);
|
||||
this.uiContextService.SendFrameUIMessage(panesFrame, UIMessage.kFrameMessage_0x4a, null, &newSelectedIdx);
|
||||
return newSelectedIdx == idx;
|
||||
}
|
||||
}
|
||||
@@ -380,13 +397,12 @@ public sealed class CharacterSelectService(
|
||||
|
||||
foreach (var charContext in *availableCharsContext.Pointer)
|
||||
{
|
||||
if (charContext.Uuid.ToString() != uuid)
|
||||
if ((*(Uuid*)charContext.Uuid).ToString() != uuid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var nameSpan = charContext.Name.AsSpan();
|
||||
var name = new string(nameSpan[..nameSpan.IndexOf('\0')]);
|
||||
var name = new string(charContext.Name);
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -399,10 +415,10 @@ public sealed class CharacterSelectService(
|
||||
{
|
||||
await this.gameThreadService.QueueOnGameThread(() =>
|
||||
{
|
||||
var logoutMessage = new LogOutMessage(0, 1); // Changed to 1 for character select
|
||||
var logoutMessage = new kLogout { Unknown = 0, CharacterSelect = 1 };
|
||||
unsafe
|
||||
{
|
||||
this.uiContextService.SendMessage(UIMessage.Logout, (uint)&logoutMessage, 0);
|
||||
this.uiContextService.SendMessage(UIMessage.kLogout, (uint)&logoutMessage, 0);
|
||||
}
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Daybreak.API.Interop;
|
||||
using Daybreak.API.Interop.GuildWars;
|
||||
using Daybreak.API.Models;
|
||||
using Daybreak.API.Services.Interop;
|
||||
using System.Core.Extensions;
|
||||
using System.Extensions;
|
||||
@@ -70,8 +69,15 @@ public sealed class ChatService(
|
||||
span[^2] = '\u0001';
|
||||
});
|
||||
|
||||
using var packet = new UnmanagedStruct<UIPackets.UIChatMessage>(new UIPackets.UIChatMessage(channel, encoded, channel));
|
||||
this.uiContextService.SendMessage(UIMessage.WriteToChatLog, (nuint)packet.Address, 0x0);
|
||||
unsafe
|
||||
{
|
||||
fixed (char* encodedPtr = encoded)
|
||||
{
|
||||
using var packet = new UnmanagedStruct<kPrintChatMessage>(new kPrintChatMessage { Channel = (GWCA.GW.Chat.Channel)channel, Message = (nint)encodedPtr });
|
||||
this.uiContextService.SendMessage(UIMessage.kWriteToChatLog, (nuint)packet.Address, 0x0);
|
||||
}
|
||||
}
|
||||
|
||||
}, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,7 @@ namespace Daybreak.API.Services.Interop;
|
||||
|
||||
public unsafe sealed class AgentContextService
|
||||
{
|
||||
public WrappedPointer<GuildWarsArray<WrappedPointer<AgentContext>>> GetAgentArray()
|
||||
{
|
||||
// GuildWarsArray<nint> and GuildWarsArray<WrappedPointer<AgentContext>> have the same memory layout
|
||||
// since both nint and WrappedPointer<T> are pointer-sized
|
||||
return (GuildWarsArray<WrappedPointer<AgentContext>>*)GWCA.GW.Agents.GetAgentArray();
|
||||
}
|
||||
public uint GetPlayerAgentId() => GWCA.GW.PlayerMgr.GetPlayerAgentId(0);
|
||||
|
||||
public uint GetPlayerAgentId()
|
||||
{
|
||||
return GWCA.GW.PlayerMgr.GetPlayerAgentId(0);
|
||||
}
|
||||
public Agent* GetAgentById(uint agentId) => GWCA.GW.Agents.GetAgentByID(agentId);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ public unsafe sealed class GameContextService
|
||||
|
||||
public WrappedPointer<PreGameContext> GetPreGameContext() => GWCA.GW.GetPreGameContext();
|
||||
|
||||
public WrappedPointer<GuildWarsArray<CharInfoContext>> GetAvailableChars() => GWCA.GW.GetAvailableChars();
|
||||
public WrappedPointer<GuildWarsArray<CharacterInformation>> GetAvailableChars() => GWCA.GW.GetAvailableChars();
|
||||
|
||||
public bool IsMapLoaded() => GWCA.GW.Map.GetIsMapLoaded();
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ public sealed unsafe class InstanceContextService
|
||||
{
|
||||
public WrappedPointer<AreaInfo> GetAreaInfo() => GWCA.GW.Map.GetMapInfo(0);
|
||||
|
||||
public ServerRegion GetServerRegion() => GWCA.GW.Map.GetRegion();
|
||||
public ServerRegion GetServerRegion() => (Daybreak.API.Interop.GuildWars.ServerRegion)GWCA.GW.Map.GetRegion();
|
||||
|
||||
public InstanceType GetInstanceType() => GWCA.GW.Map.GetInstanceType();
|
||||
public InstanceType GetInstanceType() => (Daybreak.API.Interop.GuildWars.InstanceType)GWCA.GW.Map.GetInstanceType();
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
using Daybreak.API.Interop;
|
||||
using static Daybreak.API.Interop.GWCA.GW.Constants;
|
||||
|
||||
namespace Daybreak.API.Services.Interop;
|
||||
|
||||
public sealed class PartyContextService
|
||||
{
|
||||
public bool AddHero(uint heroId) => GWCA.GW.PartyMgr.AddHero((int)heroId);
|
||||
public bool AddHero(uint heroId) => GWCA.GW.PartyMgr.AddHero((HeroID)heroId);
|
||||
|
||||
public bool KickHero(uint heroId) => GWCA.GW.PartyMgr.KickHero((int)heroId);
|
||||
public bool KickHero(uint heroId) => GWCA.GW.PartyMgr.KickHero((HeroID)heroId);
|
||||
|
||||
public bool KickAllHeroes() => GWCA.GW.PartyMgr.KickAllHeroes();
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Daybreak.API.Services.Interop;
|
||||
|
||||
public sealed class PreferencesService()
|
||||
{
|
||||
public uint? GetEnumPreference(EnumPreference pref) => GWCA.GW.UI.GetPreference(pref);
|
||||
public uint? GetEnumPreference(EnumPreference pref) => GWCA.GW.UI.GetPreference((GWCA.GW.UI.EnumPreference)pref);
|
||||
|
||||
public bool SetEnumPreference(EnumPreference pref, uint value) => GWCA.GW.UI.SetPreference(pref, value);
|
||||
public bool SetEnumPreference(EnumPreference pref, uint value) => GWCA.GW.UI.SetPreference((GWCA.GW.UI.EnumPreference)pref, value);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Daybreak.API.Interop;
|
||||
using Daybreak.API.Interop.GuildWars;
|
||||
using Daybreak.API.Models;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Core.Extensions;
|
||||
using System.Extensions.Core;
|
||||
@@ -23,21 +22,7 @@ public sealed class UIContextService(ILogger<UIContextService> logger)
|
||||
public unsafe WrappedPointer<T> GetFrameContext<T>(WrappedPointer<Frame> frame)
|
||||
where T : unmanaged
|
||||
{
|
||||
if (frame.IsNull || frame.Pointer->FrameCallbacks.Size == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < frame.Pointer->FrameCallbacks.Size; i++)
|
||||
{
|
||||
var callback = frame.Pointer->FrameCallbacks.Buffer[i];
|
||||
if (callback.UiCtl_Context != null)
|
||||
{
|
||||
return new WrappedPointer<T>((T*)callback.UiCtl_Context);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return (T*)GWCA.GW.UI.GetFrameContext(frame.Pointer);
|
||||
}
|
||||
|
||||
public unsafe WrappedPointer<Frame> GetChildFrame(WrappedPointer<Frame> parent, uint childOffset)
|
||||
@@ -66,16 +51,16 @@ public sealed class UIContextService(ILogger<UIContextService> logger)
|
||||
return false;
|
||||
}
|
||||
|
||||
return GWCA.GW.UI.SendFrameUIMessage(frame, messageId, arg1, (nint)arg2);
|
||||
return GWCA.GW.UI.SendFrameUIMessage(frame, (GWCA.GW.UI.UIMessage)messageId, arg1, (nint)arg2);
|
||||
}
|
||||
|
||||
public unsafe bool SetFrameDisabled(WrappedPointer<Frame> frame, bool disabled) => GWCA.GW.UI.SetFrameDisabled(frame, disabled);
|
||||
|
||||
public unsafe bool SetFrameVisible(WrappedPointer<Frame> frame, bool visible) => GWCA.GW.UI.SetFrameVisible(frame, visible);
|
||||
|
||||
public unsafe bool KeyDown(ControlAction action, WrappedPointer<Frame> frame) => GWCA.GW.UI.Keydown(action, frame);
|
||||
public unsafe bool KeyDown(GWCA.GW.UI.ControlAction action, WrappedPointer<Frame> frame) => GWCA.GW.UI.Keydown(action, frame);
|
||||
|
||||
public unsafe bool KeyUp(ControlAction action, WrappedPointer<Frame> frame) => GWCA.GW.UI.Keyup(action, frame);
|
||||
public unsafe bool KeyUp(GWCA.GW.UI.ControlAction action, WrappedPointer<Frame> frame) => GWCA.GW.UI.Keyup(action, frame);
|
||||
|
||||
public unsafe WrappedPointer<Frame> GetFrameByLabel(string label)
|
||||
{
|
||||
@@ -107,9 +92,9 @@ public sealed class UIContextService(ILogger<UIContextService> logger)
|
||||
return GWCA.GW.UI.ButtonClick(frame);
|
||||
}
|
||||
|
||||
public unsafe void SendMessage(UIMessage message, nuint wParam, nuint lParam) => GWCA.GW.UI.SendUIMessage(message, (void*)wParam, (nint)lParam);
|
||||
public unsafe void SendMessage(UIMessage message, nuint wParam, nuint lParam) => GWCA.GW.UI.SendUIMessage((GWCA.GW.UI.UIMessage)message, (void*)wParam, (nint)lParam);
|
||||
|
||||
public unsafe Task<string> AsyncDecodeStringAsync(ushort* encodedString, Language language = Language.Unknown, CancellationToken cancellationToken = default)
|
||||
public unsafe Task<string> AsyncDecodeStringAsync(ushort* encodedString, GWCA.GW.Constants.Language language = GWCA.GW.Constants.Language.Unknown, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var taskCompletionSource = new TaskCompletionSource<string>();
|
||||
cancellationToken.Register(() => taskCompletionSource.TrySetCanceled(cancellationToken));
|
||||
@@ -150,7 +135,7 @@ public sealed class UIContextService(ILogger<UIContextService> logger)
|
||||
return taskCompletionSource.Task;
|
||||
}
|
||||
|
||||
public unsafe Task<string> AsyncDecodeStringAsync(string encodedString, Language language = Language.Unknown, CancellationToken cancellationToken = default)
|
||||
public unsafe Task<string> AsyncDecodeStringAsync(string encodedString, GWCA.GW.Constants.Language language = GWCA.GW.Constants.Language.Unknown, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// Pin the string and convert to ushort*
|
||||
fixed (char* encodedPtr = encodedString)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using Daybreak.API.Interop;
|
||||
using Daybreak.API.Interop.GuildWars;
|
||||
using Daybreak.API.Services.Interop;
|
||||
using Daybreak.Shared.Models.Api;
|
||||
using Daybreak.Shared.Models.Guildwars;
|
||||
using System.Extensions.Core;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Daybreak.API.Services;
|
||||
@@ -32,45 +34,48 @@ public sealed class InventoryService(
|
||||
return default;
|
||||
}
|
||||
|
||||
var inventory = gameContext.Pointer->ItemContext->Inventory;
|
||||
if (inventory.IsNull)
|
||||
var inventory = gameContext.Pointer->Items->Inventory;
|
||||
if (inventory is null)
|
||||
{
|
||||
scopedLogger.LogError("Inventory is null");
|
||||
return default;
|
||||
}
|
||||
|
||||
var itemTuples = new List<(BagType Type, List<(uint ModelId, string EncodedCompleteName, string EncodedSingleName, string EncodedName, bool Inscribable, int Quantity, uint[] Modifiers, ItemType ItemType, uint Interaction, uint ModelFileId)>)>();
|
||||
foreach (var bag in inventory.Pointer->Bags)
|
||||
var itemTuples = new List<(GWCA.GW.Constants.BagType Type, List<(uint ModelId, string EncodedCompleteName, string EncodedSingleName, string EncodedName, bool Inscribable, int Quantity, uint[] Modifiers, ItemType ItemType, uint Interaction, uint ModelFileId)>)>();
|
||||
var bags = (BagStruct**)Unsafe.AsPointer(ref inventory->Bags);
|
||||
for (var i = 0; i < 23; i++)
|
||||
{
|
||||
var bag = bags[i];
|
||||
if (bag is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var retBag = new List<(uint ModelId, string EncodedCompleteName, string EncodedSingleName, string EncodedName, bool Inscribable, int Quantity, uint[] Modifiers, ItemType ItemType, uint Interaction, uint ModelFileId)>();
|
||||
itemTuples.Add((bag->Type, retBag));
|
||||
itemTuples.Add((bag->BagType, retBag));
|
||||
if (bag->ItemsCount is 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var item in bag->Items)
|
||||
foreach (var itemPtr in bag->Items.Value)
|
||||
{
|
||||
if (item.IsNull)
|
||||
if (itemPtr is 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var singleItemName = new string(item.Pointer->SingleItemName);
|
||||
var nameEncoded = new string(item.Pointer->NameEncoded);
|
||||
var completeNameEncoded = new string(item.Pointer->CompleteNameEncoded);
|
||||
var modifiers = new uint[item.Pointer->ModifiersCount];
|
||||
for (var j = 0; j < item.Pointer->ModifiersCount; j++)
|
||||
var item = (ItemStruct*)itemPtr;
|
||||
var singleItemName = new string((char*)item->SingleItemName);
|
||||
var nameEncoded = new string((char*)item->NameEnc);
|
||||
var completeNameEncoded = new string((char*)item->CompleteNameEnc);
|
||||
var modifiers = new uint[item->ModStructSize];
|
||||
for (var j = 0; j < item->ModStructSize; j++)
|
||||
{
|
||||
modifiers[j] = item.Pointer->Modifiers[j].Mod;
|
||||
modifiers[j] = item->ModStruct[j].Mod;
|
||||
}
|
||||
|
||||
retBag.Add((item.Pointer->ModelId, completeNameEncoded, singleItemName, nameEncoded, item.Pointer->Inscribable, item.Pointer->Quantity, modifiers, item.Pointer->Type, item.Pointer->Interaction, item.Pointer->ModelFileId));
|
||||
retBag.Add((item->ModelId, completeNameEncoded, singleItemName, nameEncoded, (item->Interaction & 0x08000000) != 0, item->Quantity, modifiers, (ItemType)item->Type, item->Interaction, item->ModelFileId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,17 +90,18 @@ public sealed class InventoryService(
|
||||
|
||||
// Decode strings sequentially to avoid race conditions with the game's TextParser language field.
|
||||
// Parallel decoding causes crashes because multiple operations race to set/restore the language.
|
||||
var decodedItemTuples = new List<(BagType Type, List<(uint ModelId, string EncodedName, string? DecodedName, string EncodedSingleName, string? DecodedSingleName, string EncodedCompleteName, string? DecodedCompleteName, bool Inscribable, int Quantity, uint[] Modifiers, ItemType ItemType, uint Interaction, uint ModelFileId)> Items)>();
|
||||
var decodedItemTuples = new List<(GWCA.GW.Constants.BagType Type, List<(uint ModelId, string EncodedName, string? DecodedName, string EncodedSingleName, string? DecodedSingleName, string EncodedCompleteName, string? DecodedCompleteName, bool Inscribable, int Quantity, uint[] Modifiers, ItemType ItemType, uint Interaction, uint ModelFileId)> Items)>();
|
||||
foreach (var tuple in itemTuples)
|
||||
{
|
||||
var decodedItems = new List<(uint ModelId, string EncodedName, string? DecodedName, string EncodedSingleName, string? DecodedSingleName, string EncodedCompleteName, string? DecodedCompleteName, bool Inscribable, int Quantity, uint[] Modifiers, ItemType ItemType, uint Interaction, uint ModelFileId)>();
|
||||
foreach (var item in tuple.Item2)
|
||||
{
|
||||
var decodedName = await this.uIService.DecodeString(item.EncodedName, Language.English, cancellationToken);
|
||||
var decodedCompleteName = await this.uIService.DecodeString(item.EncodedCompleteName, Language.English, cancellationToken);
|
||||
var decodedSingleName = await this.uIService.DecodeString(item.EncodedSingleName, Language.English, cancellationToken);
|
||||
var decodedName = await this.uIService.DecodeString(item.EncodedName, (GWCA.GW.Constants.Language)Language.English, cancellationToken);
|
||||
var decodedCompleteName = await this.uIService.DecodeString(item.EncodedCompleteName, (GWCA.GW.Constants.Language)Language.English, cancellationToken);
|
||||
var decodedSingleName = await this.uIService.DecodeString(item.EncodedSingleName, (GWCA.GW.Constants.Language)Language.English, cancellationToken);
|
||||
decodedItems.Add((item.ModelId, item.EncodedName, decodedName, item.EncodedSingleName, decodedSingleName, item.EncodedCompleteName, decodedCompleteName, item.Inscribable, item.Quantity, item.Modifiers, item.ItemType, item.Interaction, item.ModelFileId));
|
||||
}
|
||||
|
||||
decodedItemTuples.Add((tuple.Type, decodedItems));
|
||||
}
|
||||
|
||||
|
||||
@@ -22,16 +22,14 @@ public sealed class LoginService(
|
||||
unsafe
|
||||
{
|
||||
var gameContext = this.gameContextService.GetGameContext();
|
||||
if (gameContext.IsNull || gameContext.Pointer->CharContext is null)
|
||||
if (gameContext.IsNull || gameContext.Pointer->Character is null)
|
||||
{
|
||||
scopedLogger.LogError("Game context is not initialized");
|
||||
return default;
|
||||
}
|
||||
|
||||
var playerNameSpan = gameContext.Pointer->CharContext->PlayerName.AsSpan();
|
||||
var playerName = new string(playerNameSpan[..playerNameSpan.IndexOf('\0')]);
|
||||
var emailSpan = gameContext.Pointer->CharContext->PlayerEmail.AsSpan();
|
||||
var email = new string(emailSpan[..emailSpan.IndexOf('\0')]);
|
||||
var playerName = new string(gameContext.Pointer->Character->PlayerName);
|
||||
var email = new string(gameContext.Pointer->Character->PlayerEmail);
|
||||
return new LoginInfo(email, playerName);
|
||||
}
|
||||
}, cancellationToken);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Daybreak.API.Extensions;
|
||||
using Daybreak.API.Interop;
|
||||
using Daybreak.API.Interop.GuildWars;
|
||||
using Daybreak.API.Models;
|
||||
using Daybreak.API.Services.Interop;
|
||||
@@ -72,7 +73,7 @@ public sealed class MainPlayerService : IDisposable
|
||||
|
||||
var gameContext = this.gameContextService.GetGameContext();
|
||||
if (gameContext.IsNull ||
|
||||
gameContext.Pointer->WorldContext is null)
|
||||
gameContext.Pointer->World is null)
|
||||
{
|
||||
scopedLogger.LogError("Failed to get game context");
|
||||
return false;
|
||||
@@ -85,23 +86,23 @@ public sealed class MainPlayerService : IDisposable
|
||||
return false;
|
||||
}
|
||||
|
||||
var playerAgent = this.GetAgentContext(playerAgentId);
|
||||
var playerAgent = this.agentContextService.GetAgentById(playerAgentId);
|
||||
if (playerAgent is null ||
|
||||
playerAgent->Type is not AgentType.Living ||
|
||||
playerAgent->Type is not (uint)AgentType.Living ||
|
||||
playerAgent->AgentId != playerAgentId)
|
||||
{
|
||||
scopedLogger.LogError("Player agent {playerAgentId} not found in agent array", playerAgentId);
|
||||
return false;
|
||||
}
|
||||
|
||||
var livingAgent = (AgentLivingContext*)playerAgent;
|
||||
if (livingAgent->Level != gameContext.Pointer->WorldContext->Level)
|
||||
var livingAgent = (AgentLiving*)playerAgent;
|
||||
if (livingAgent->Level != gameContext.Pointer->World->Level)
|
||||
{
|
||||
scopedLogger.LogError("Player agent not found. Player level mismatch: {level} != {gameLevel}", livingAgent->Level, gameContext.Pointer->WorldContext->Level);
|
||||
scopedLogger.LogError("Player agent not found. Player level mismatch: {level} != {gameLevel}", livingAgent->Level, gameContext.Pointer->World->Level);
|
||||
return false;
|
||||
}
|
||||
|
||||
var agentProfession = gameContext.Pointer->WorldContext->Professions.AsValueEnumerable().FirstOrDefault(p => p.AgentId == playerAgentId);
|
||||
var agentProfession = gameContext.Pointer->World->PartyProfessionStates.AsValueEnumerable().FirstOrDefault(p => p.AgentId == playerAgentId);
|
||||
if (agentProfession.AgentId != playerAgentId)
|
||||
{
|
||||
scopedLogger.LogError("Failed to find agent profession for player agent id {agentId}", playerAgentId);
|
||||
@@ -112,9 +113,9 @@ public sealed class MainPlayerService : IDisposable
|
||||
(uint)singleBuild.Primary.Id,
|
||||
(uint)singleBuild.Secondary.Id,
|
||||
singleBuild.Skills.AsValueEnumerable().Select(s => (uint)s.Id).ToArray(),
|
||||
livingAgent->Primary,
|
||||
agentProfession.UnlockedProfessionsFlags,
|
||||
[.. gameContext.Pointer->WorldContext->UnlockedCharacterSkills]);
|
||||
livingAgent->Tags->Primary,
|
||||
agentProfession.UnlockedProfessions,
|
||||
[.. gameContext.Pointer->World->UnlockedCharacterSkills]);
|
||||
|
||||
if (!this.buildTemplateManager.CanTemplateApply(validationRequest))
|
||||
{
|
||||
@@ -122,9 +123,9 @@ public sealed class MainPlayerService : IDisposable
|
||||
return false;
|
||||
}
|
||||
|
||||
var attributeIds = new Array12Uint();
|
||||
var attributeIds = new AttributeArray12();
|
||||
var attributeValues = new Array12Uint();
|
||||
var skills = new Array8Uint();
|
||||
var skills = new SkillIDArray8();
|
||||
for (var i = 0; i < singleBuild.Attributes.Count && i < 12; i++)
|
||||
{
|
||||
if (singleBuild.Attributes[i].Attribute is null)
|
||||
@@ -132,23 +133,24 @@ public sealed class MainPlayerService : IDisposable
|
||||
continue;
|
||||
}
|
||||
|
||||
attributeIds[i] = (uint)singleBuild.Attributes[i].Attribute!.Id;
|
||||
attributeIds[i] = (GWCA.GW.Constants.Attribute)singleBuild.Attributes[i].Attribute!.Id;
|
||||
attributeValues[i] = (uint)singleBuild.Attributes[i].Points;
|
||||
}
|
||||
|
||||
for (var i = 0; i < singleBuild.Skills.Count && i < 8; i++)
|
||||
{
|
||||
skills[i] = (uint)singleBuild.Skills[i].Id;
|
||||
skills[i] = (GWCA.GW.Constants.SkillID)singleBuild.Skills[i].Id;
|
||||
}
|
||||
|
||||
var skillTemplate = new SkillTemplate(
|
||||
(uint)singleBuild.Primary.Id,
|
||||
(uint)singleBuild.Secondary.Id,
|
||||
(uint)Math.Min(singleBuild.Attributes.Count, 12),
|
||||
attributeIds,
|
||||
attributeValues,
|
||||
skills);
|
||||
|
||||
var skillTemplate = new SkillTemplate
|
||||
{
|
||||
Primary = (GWCA.GW.Constants.Profession)singleBuild.Primary.Id,
|
||||
Secondary = (GWCA.GW.Constants.Profession)singleBuild.Secondary.Id,
|
||||
AttributesCount = (uint)Math.Min(singleBuild.Attributes.Count, 12),
|
||||
AttributeIds = attributeIds,
|
||||
Skills = skills,
|
||||
};
|
||||
Unsafe.CopyBlock(skillTemplate.AttributeValues, Unsafe.AsPointer(ref attributeValues), (uint)(12 * sizeof(uint)));
|
||||
this.skillbarContextService.LoadBuild(playerAgentId, &skillTemplate);
|
||||
return true;
|
||||
}
|
||||
@@ -156,11 +158,11 @@ public sealed class MainPlayerService : IDisposable
|
||||
|
||||
if (result)
|
||||
{
|
||||
await this.chatService.AddMessageAsync("Build applied successfully.", "Daybreak.API", Channel.Moderator, cancellationToken);
|
||||
await this.chatService.AddMessageAsync("Build applied successfully.", "Daybreak.API", Channel.CHANNEL_MODERATOR, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
await this.chatService.AddMessageAsync("Failed to apply build.", "Daybreak.API", Channel.Moderator, cancellationToken);
|
||||
await this.chatService.AddMessageAsync("Failed to apply build.", "Daybreak.API", Channel.CHANNEL_MODERATOR, cancellationToken);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -193,21 +195,21 @@ public sealed class MainPlayerService : IDisposable
|
||||
return default;
|
||||
}
|
||||
|
||||
var skillbarContext = gameContext.Pointer->WorldContext->Skillbars.AsValueEnumerable().FirstOrDefault(s => s.AgentId == playerAgentId);
|
||||
var skillbarContext = gameContext.Pointer->World->Skillbar.Value.AsValueEnumerable().FirstOrDefault(s => s.AgentId == playerAgentId);
|
||||
if (skillbarContext.AgentId != playerAgentId)
|
||||
{
|
||||
scopedLogger.LogError("Failed to find skillbar context for player agent id {agentId}", playerAgentId);
|
||||
return default;
|
||||
}
|
||||
|
||||
var agentAttributes = gameContext.Pointer->WorldContext->Attributes.AsValueEnumerable().FirstOrDefault(a => a.AgentId == playerAgentId);
|
||||
var agentAttributes = gameContext.Pointer->World->Attributes.Value.AsValueEnumerable().FirstOrDefault(a => a.AgentId == playerAgentId);
|
||||
if (agentAttributes.AgentId != playerAgentId)
|
||||
{
|
||||
scopedLogger.LogError("Failed to find agent attributes for player agent id {agentId}", playerAgentId);
|
||||
return default;
|
||||
}
|
||||
|
||||
var professionContext = gameContext.Pointer->WorldContext->Professions.AsValueEnumerable().FirstOrDefault(p => p.AgentId == playerAgentId);
|
||||
var professionContext = gameContext.Pointer->World->PartyProfessionStates.AsValueEnumerable().FirstOrDefault(p => p.AgentId == playerAgentId);
|
||||
if (professionContext.AgentId != playerAgentId)
|
||||
{
|
||||
scopedLogger.LogError("Failed to find agent profession for player agent id {agentId}", playerAgentId);
|
||||
@@ -215,11 +217,11 @@ public sealed class MainPlayerService : IDisposable
|
||||
}
|
||||
|
||||
return new BuildEntry(
|
||||
(int)professionContext.CurrentPrimary,
|
||||
(int)professionContext.CurrentSecondary,
|
||||
agentAttributes.Attributes.GetAttributeEntryList(),
|
||||
[skillbarContext.Skill0.Id, skillbarContext.Skill1.Id, skillbarContext.Skill2.Id, skillbarContext.Skill3.Id,
|
||||
skillbarContext.Skill4.Id, skillbarContext.Skill5.Id, skillbarContext.Skill6.Id, skillbarContext.Skill7.Id]);
|
||||
(int)professionContext.Primary,
|
||||
(int)professionContext.Secondary,
|
||||
[.. agentAttributes.Attribute.GetAttributeEntryList()],
|
||||
[(uint)skillbarContext.Skills[0].SkillId, (uint)skillbarContext.Skills[1].SkillId, (uint)skillbarContext.Skills[2].SkillId, (uint)skillbarContext.Skills[3].SkillId,
|
||||
(uint)skillbarContext.Skills[4].SkillId, (uint)skillbarContext.Skills[5].SkillId, (uint)skillbarContext.Skills[6].SkillId, (uint)skillbarContext.Skills[7].SkillId]);
|
||||
}
|
||||
}, cancellationToken);
|
||||
}
|
||||
@@ -238,15 +240,15 @@ public sealed class MainPlayerService : IDisposable
|
||||
}
|
||||
|
||||
var gameContext = this.gameContextService.GetGameContext();
|
||||
if (gameContext.IsNull || gameContext.Pointer->WorldContext is null)
|
||||
if (gameContext.IsNull || gameContext.Pointer->World is null)
|
||||
{
|
||||
scopedLogger.LogError("Game context is not initialized");
|
||||
return default;
|
||||
}
|
||||
|
||||
return new QuestLogInformation(
|
||||
gameContext.Pointer->WorldContext->ActiveQuestId,
|
||||
gameContext.Pointer->WorldContext->QuestLog.AsValueEnumerable().Select(q => new QuestInformation(q.QuestId, q.MapFrom)).ToList());
|
||||
(uint)gameContext.Pointer->World->ActiveQuestId,
|
||||
gameContext.Pointer->World->QuestLog.Value.AsValueEnumerable().Select(q => new QuestInformation((uint)q.QuestId, (uint)q.MapFrom)).ToList());
|
||||
}
|
||||
}, cancellationToken);
|
||||
}
|
||||
@@ -265,29 +267,27 @@ public sealed class MainPlayerService : IDisposable
|
||||
}
|
||||
|
||||
var gameContext = this.gameContextService.GetGameContext();
|
||||
if (gameContext.IsNull || gameContext.Pointer->CharContext is null ||
|
||||
gameContext.Pointer->WorldContext is null)
|
||||
if (gameContext.IsNull || gameContext.Pointer->Character is null ||
|
||||
gameContext.Pointer->World is null)
|
||||
{
|
||||
scopedLogger.LogError("Game context is not initialized");
|
||||
return default;
|
||||
}
|
||||
|
||||
var playerNameSpan = gameContext.Pointer->CharContext->PlayerName.AsSpan();
|
||||
var playerName = new string(playerNameSpan[..playerNameSpan.IndexOf('\0')]);
|
||||
var emailSpan = gameContext.Pointer->CharContext->PlayerEmail.AsSpan();
|
||||
var email = new string(emailSpan[..emailSpan.IndexOf('\0')]);
|
||||
var accountName = new string(gameContext.Pointer->WorldContext->AccountInfo->AccountName);
|
||||
var playerName = new string (gameContext.Pointer->Character->PlayerName);
|
||||
var email = new string(gameContext.Pointer->Character->PlayerEmail);
|
||||
var accountName = new string((char*)gameContext.Pointer->World->AccountInfo->AccountName);
|
||||
return new MainPlayerInformation(
|
||||
gameContext.Pointer->CharContext->PlayerUuid.ToString(),
|
||||
(*(Uuid*)gameContext.Pointer->Character->PlayerUuid).ToString(),
|
||||
email,
|
||||
playerName,
|
||||
accountName,
|
||||
gameContext.Pointer->WorldContext->AccountInfo->Wins,
|
||||
gameContext.Pointer->WorldContext->AccountInfo->Losses,
|
||||
gameContext.Pointer->WorldContext->AccountInfo->Rating,
|
||||
gameContext.Pointer->WorldContext->AccountInfo->QualifierPoints,
|
||||
gameContext.Pointer->WorldContext->AccountInfo->Rank,
|
||||
gameContext.Pointer->WorldContext->AccountInfo->TournamentRewardPoints);
|
||||
gameContext.Pointer->World->AccountInfo->Wins,
|
||||
gameContext.Pointer->World->AccountInfo->Losses,
|
||||
gameContext.Pointer->World->AccountInfo->Rating,
|
||||
gameContext.Pointer->World->AccountInfo->QualifierPoints,
|
||||
gameContext.Pointer->World->AccountInfo->Rank,
|
||||
gameContext.Pointer->World->AccountInfo->TournamentRewardPoints);
|
||||
}
|
||||
}, cancellationToken);
|
||||
}
|
||||
@@ -306,61 +306,57 @@ public sealed class MainPlayerService : IDisposable
|
||||
}
|
||||
|
||||
var gameContext = this.gameContextService.GetGameContext();
|
||||
var agentArray = this.agentContextService.GetAgentArray();
|
||||
var playerAgentId = this.agentContextService.GetPlayerAgentId();
|
||||
if (gameContext.IsNull ||
|
||||
gameContext.Pointer->WorldContext is null ||
|
||||
gameContext.Pointer->CharContext is null ||
|
||||
gameContext.Pointer->WorldContext->MapAgents.Buffer is null ||
|
||||
agentArray.IsNull ||
|
||||
agentArray.Pointer->Buffer is null ||
|
||||
gameContext.Pointer->World is null ||
|
||||
gameContext.Pointer->Character is null ||
|
||||
playerAgentId is 0x0)
|
||||
{
|
||||
scopedLogger.LogDebug("Game data is not yet initialized");
|
||||
return default;
|
||||
}
|
||||
|
||||
var playerAgent = this.GetAgentContext(playerAgentId);
|
||||
var playerAgent = this.agentContextService.GetAgentById(playerAgentId);
|
||||
if (playerAgent is null ||
|
||||
playerAgent->Type is not AgentType.Living ||
|
||||
playerAgent->Type is not (uint)AgentType.Living ||
|
||||
playerAgent->AgentId != playerAgentId)
|
||||
{
|
||||
scopedLogger.LogError("Player agent {playerAgentId} not found in agent array", playerAgentId);
|
||||
return default;
|
||||
}
|
||||
|
||||
var livingAgent = (AgentLivingContext*)playerAgent;
|
||||
if (livingAgent->Level != gameContext.Pointer->WorldContext->Level)
|
||||
var livingAgent = (AgentLiving*)playerAgent;
|
||||
if (livingAgent->Level != gameContext.Pointer->World->Level)
|
||||
{
|
||||
scopedLogger.LogError("Player agent not found. Player level mismatch: {level} != {gameLevel}", livingAgent->Level, gameContext.Pointer->WorldContext->Level);
|
||||
scopedLogger.LogError("Player agent not found. Player level mismatch: {level} != {gameLevel}", livingAgent->Level, gameContext.Pointer->World->Level);
|
||||
return default;
|
||||
}
|
||||
|
||||
return new MainPlayerState(
|
||||
gameContext.Pointer->WorldContext->Experience,
|
||||
gameContext.Pointer->WorldContext->Level,
|
||||
gameContext.Pointer->World->Experience,
|
||||
gameContext.Pointer->World->Level,
|
||||
|
||||
gameContext.Pointer->WorldContext->CurrentLuxon,
|
||||
gameContext.Pointer->WorldContext->CurrentKurzick,
|
||||
gameContext.Pointer->WorldContext->CurrentImperial,
|
||||
gameContext.Pointer->WorldContext->CurrentBalthazar,
|
||||
gameContext.Pointer->WorldContext->MaxLuxon,
|
||||
gameContext.Pointer->WorldContext->MaxKurzick,
|
||||
gameContext.Pointer->WorldContext->MaxImperial,
|
||||
gameContext.Pointer->WorldContext->MaxBalthazar,
|
||||
gameContext.Pointer->WorldContext->TotalLuxon,
|
||||
gameContext.Pointer->WorldContext->TotalKurzick,
|
||||
gameContext.Pointer->WorldContext->TotalImperial,
|
||||
gameContext.Pointer->WorldContext->TotalBalthazar,
|
||||
gameContext.Pointer->World->CurrentLuxon,
|
||||
gameContext.Pointer->World->CurrentKurzick,
|
||||
gameContext.Pointer->World->CurrentImperial,
|
||||
gameContext.Pointer->World->CurrentBalth,
|
||||
gameContext.Pointer->World->MaxLuxon,
|
||||
gameContext.Pointer->World->MaxKurzick,
|
||||
gameContext.Pointer->World->MaxImperial,
|
||||
gameContext.Pointer->World->MaxBalth,
|
||||
gameContext.Pointer->World->TotalEarnedLuxon,
|
||||
gameContext.Pointer->World->TotalEarnedKurzick,
|
||||
gameContext.Pointer->World->TotalEarnedImperial,
|
||||
gameContext.Pointer->World->TotalEarnedBalth,
|
||||
|
||||
// Energy and health are percentages of Max
|
||||
livingAgent->Health * livingAgent->MaxHealth,
|
||||
livingAgent->MaxHealth,
|
||||
livingAgent->Hp * livingAgent->MaxHp,
|
||||
livingAgent->MaxHp,
|
||||
livingAgent->Energy * livingAgent->MaxEnergy,
|
||||
livingAgent->MaxEnergy,
|
||||
|
||||
livingAgent->Primary,
|
||||
livingAgent->Secondary,
|
||||
livingAgent->Tags->Primary,
|
||||
livingAgent->Tags->Secondary,
|
||||
|
||||
playerAgent->Pos.X,
|
||||
playerAgent->Pos.Y
|
||||
@@ -386,18 +382,17 @@ public sealed class MainPlayerService : IDisposable
|
||||
var currentMapInfo = this.instanceContextService.GetAreaInfo();
|
||||
var serverRegion = this.instanceContextService.GetServerRegion();
|
||||
if (gameContext.IsNull ||
|
||||
gameContext.Pointer->CharContext is null ||
|
||||
gameContext.Pointer->WorldContext is null ||
|
||||
gameContext.Pointer->PartyContext is null ||
|
||||
gameContext.Pointer->Character is null ||
|
||||
gameContext.Pointer->World is null ||
|
||||
gameContext.Pointer->Party is 0 ||
|
||||
currentMapInfo.IsNull)
|
||||
{
|
||||
scopedLogger.LogError("Game context is not initialized");
|
||||
return new InstanceInfo(0, 0, 0, 0, Shared.Models.Api.InstanceType.Loading, DistrictRegionInfo.Unknown, LanguageInfo.Unknown, CampaignInfo.Unknown, ContinentInfo.Unknown, RegionInfo.Unknown, DifficultyInfo.Unknown);
|
||||
}
|
||||
|
||||
var charContext = *gameContext.Pointer->CharContext;
|
||||
var worldContext = *gameContext.Pointer->WorldContext;
|
||||
var partyContext = *gameContext.Pointer->PartyContext;
|
||||
var charContext = *gameContext.Pointer->Character;
|
||||
var worldContext = *gameContext.Pointer->World;
|
||||
var mapInfo = *currentMapInfo.Pointer;
|
||||
var mapId = charContext.MapId;
|
||||
var language = charContext.Language;
|
||||
@@ -406,7 +401,7 @@ public sealed class MainPlayerService : IDisposable
|
||||
var foesToKill = worldContext.FoesToKill;
|
||||
|
||||
return new InstanceInfo(
|
||||
MapId: charContext.MapId,
|
||||
MapId: (uint)charContext.MapId,
|
||||
DistrictNumber: charContext.DistrictNumber,
|
||||
FoesKilled: worldContext.FoesKilled,
|
||||
FoesToKill: worldContext.FoesToKill,
|
||||
@@ -416,7 +411,7 @@ public sealed class MainPlayerService : IDisposable
|
||||
Campaign: (CampaignInfo)mapInfo.Campaign,
|
||||
Continent: (ContinentInfo)mapInfo.Continent,
|
||||
Region: (RegionInfo)mapInfo.Region,
|
||||
Difficulty: partyContext.Flags.HasFlag(PartyFlags.HardMode) ? DifficultyInfo.Hard : DifficultyInfo.Normal);
|
||||
Difficulty: GWCA.GW.PartyMgr.GetIsPartyInHardMode() ? DifficultyInfo.Hard : DifficultyInfo.Normal);
|
||||
}
|
||||
}, cancellationToken);
|
||||
}
|
||||
@@ -435,27 +430,26 @@ public sealed class MainPlayerService : IDisposable
|
||||
}
|
||||
|
||||
var gameContext = this.gameContextService.GetGameContext();
|
||||
if (gameContext.IsNull || gameContext.Pointer->WorldContext is null)
|
||||
if (gameContext.IsNull || gameContext.Pointer->World is null)
|
||||
{
|
||||
scopedLogger.LogError("Game context is not initialized");
|
||||
return default;
|
||||
}
|
||||
|
||||
var playerIndex = gameContext.Pointer->CharContext->PlayerNumber;
|
||||
var players = gameContext.Pointer->WorldContext->Players;
|
||||
if (playerIndex < 0 || playerIndex >= players.Size)
|
||||
var playerIndex = gameContext.Pointer->Character->PlayerNumber;
|
||||
var player = GWCA.GW.PlayerMgr.GetPlayerByID(playerIndex);
|
||||
if (player is null)
|
||||
{
|
||||
scopedLogger.LogError("Failed to get player id. Got {playerNumber}", playerIndex);
|
||||
scopedLogger.LogError("Failed to get player");
|
||||
return default;
|
||||
}
|
||||
|
||||
var player = gameContext.Pointer->WorldContext->Players[(int)playerIndex];
|
||||
var currentTier = player.ActiveTitleTier;
|
||||
TitleContext? currentTitle = default;
|
||||
var currentTier = player->ActiveTitleTier;
|
||||
Title? currentTitle = default;
|
||||
int? id = -1;
|
||||
for (var i = 0; i < gameContext.Pointer->WorldContext->Titles.Size; i++)
|
||||
for (var i = 0; i < gameContext.Pointer->World->Titles.Value.Size; i++)
|
||||
{
|
||||
var title = gameContext.Pointer->WorldContext->Titles.Skip(i).FirstOrDefault();
|
||||
var title = gameContext.Pointer->World->Titles.Value.Skip(i).FirstOrDefault();
|
||||
if (title.CurrentTitleTierIndex == currentTier)
|
||||
{
|
||||
currentTitle = title;
|
||||
@@ -470,15 +464,15 @@ public sealed class MainPlayerService : IDisposable
|
||||
return default;
|
||||
}
|
||||
|
||||
var titleTier = gameContext.Pointer->WorldContext->TitleTiers.Skip((int)currentTitle.Value.CurrentTitleTierIndex).FirstOrDefault();
|
||||
var titleTier = gameContext.Pointer->World->TitleTiers.Skip((int)currentTitle.Value.CurrentTitleTierIndex).FirstOrDefault();
|
||||
return new TitleInfo
|
||||
(
|
||||
Id: (uint)id,
|
||||
IsPercentage: currentTitle.Value.Props.HasFlag(TitleProps.PercentageBased),
|
||||
PointsForCurrentRank: currentTitle.Value.PointsNeededForCurrentRank,
|
||||
IsPercentage: currentTitle.Value.IsPercentageBased(),
|
||||
PointsForCurrentRank: currentTitle.Value.PointsNeededCurrentRank,
|
||||
PointsForNextRank: titleTier.TierNumber == currentTitle.Value.MaxTitleRank ?
|
||||
currentTitle.Value.CurrentPoints :
|
||||
currentTitle.Value.PointsNeededForNextRank,
|
||||
currentTitle.Value.PointsNeededNextRank,
|
||||
CurrentPoints: currentTitle.Value.CurrentPoints,
|
||||
TierNumber: titleTier.TierNumber,
|
||||
MaxTierNumber: currentTitle.Value.MaxTitleTierIndex
|
||||
@@ -502,8 +496,8 @@ public sealed class MainPlayerService : IDisposable
|
||||
|
||||
var gameContext = this.gameContextService.GetGameContext();
|
||||
if (gameContext.IsNull ||
|
||||
gameContext.Pointer->AccountContext is null ||
|
||||
gameContext.Pointer->WorldContext is null)
|
||||
gameContext.Pointer->Account is null ||
|
||||
gameContext.Pointer->World is null)
|
||||
{
|
||||
this.logger.LogError("Game context is not initialized");
|
||||
return default;
|
||||
@@ -516,7 +510,7 @@ public sealed class MainPlayerService : IDisposable
|
||||
return default;
|
||||
}
|
||||
|
||||
var agentProfession = gameContext.Pointer->WorldContext->Professions.AsValueEnumerable().FirstOrDefault(p => p.AgentId == playerAgentId);
|
||||
var agentProfession = gameContext.Pointer->World->PartyProfessionStates.AsValueEnumerable().FirstOrDefault(p => p.AgentId == playerAgentId);
|
||||
if (agentProfession.AgentId != playerAgentId)
|
||||
{
|
||||
scopedLogger.LogError("Failed to find agent profession for player agent id {agentId}", playerAgentId);
|
||||
@@ -524,25 +518,11 @@ public sealed class MainPlayerService : IDisposable
|
||||
}
|
||||
|
||||
return new MainPlayerBuildContext(
|
||||
PrimaryProfessionId: (uint)agentProfession.CurrentPrimary,
|
||||
UnlockedProfessions: agentProfession.UnlockedProfessionsFlags,
|
||||
UnlockedAccountSkills: gameContext.Pointer->AccountContext->UnlockedAccountSkills.AsValueEnumerable().ToArray(),
|
||||
UnlockedCharacterSkills: gameContext.Pointer->WorldContext->UnlockedCharacterSkills.AsValueEnumerable().ToArray());
|
||||
PrimaryProfessionId: (uint)agentProfession.Primary,
|
||||
UnlockedProfessions: agentProfession.UnlockedProfessions,
|
||||
UnlockedCharacterSkills: gameContext.Pointer->World->UnlockedCharacterSkills.AsValueEnumerable().ToArray());
|
||||
|
||||
}
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private unsafe AgentContext* GetAgentContext(uint agentId)
|
||||
{
|
||||
var agentArray = this.agentContextService.GetAgentArray();
|
||||
if (agentArray.IsNull || agentArray.Pointer->Buffer is null ||
|
||||
agentArray.Pointer->Size <= agentId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return agentArray.Pointer->Buffer[agentId].Pointer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Daybreak.API.Extensions;
|
||||
using Daybreak.API.Interop;
|
||||
using Daybreak.API.Interop.GuildWars;
|
||||
using Daybreak.API.Models;
|
||||
using Daybreak.API.Services.Interop;
|
||||
@@ -9,6 +10,7 @@ using Daybreak.Shared.Services.BuildTemplates;
|
||||
using System.Core.Extensions;
|
||||
using System.Extensions;
|
||||
using System.Extensions.Core;
|
||||
using System.Runtime.CompilerServices;
|
||||
using ZLinq;
|
||||
using InstanceType = Daybreak.API.Interop.GuildWars.InstanceType;
|
||||
|
||||
@@ -46,21 +48,21 @@ public sealed class PartyService(
|
||||
if (!await this.IsInValidOutpost(cancellationToken))
|
||||
{
|
||||
scopedLogger.LogError("Could not set party loadout. Not in a valid outpost");
|
||||
await this.chatService.AddMessageAsync("Cannot set party loadout. Not in a valid outpost.", "Daybreak.API", Channel.Moderator, cancellationToken);
|
||||
await this.chatService.AddMessageAsync("Cannot set party loadout. Not in a valid outpost.", "Daybreak.API", Channel.CHANNEL_MODERATOR, cancellationToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!await this.KickAllHeroes(cancellationToken))
|
||||
{
|
||||
scopedLogger.LogError("Could not set party loadout. Could not leave party");
|
||||
await this.chatService.AddMessageAsync("Cannot set party loadout. Could not leave party.", "Daybreak.API", Channel.Moderator, cancellationToken);
|
||||
await this.chatService.AddMessageAsync("Cannot set party loadout. Could not leave party.", "Daybreak.API", Channel.CHANNEL_MODERATOR, cancellationToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!await this.gameThreadService.QueueOnGameThread(() => this.SpawnHeroes(partyLoadout), cancellationToken))
|
||||
{
|
||||
scopedLogger.LogError("Could not set party loadout. Could not spawn heroes");
|
||||
await this.chatService.AddMessageAsync("Cannot set party loadout. Could not spawn heroes.", "Daybreak.API", Channel.Moderator, cancellationToken);
|
||||
await this.chatService.AddMessageAsync("Cannot set party loadout. Could not spawn heroes.", "Daybreak.API", Channel.CHANNEL_MODERATOR, cancellationToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -69,21 +71,21 @@ public sealed class PartyService(
|
||||
if (!await this.gameThreadService.QueueOnGameThread(() => this.ApplyBuilds(partyLoadout), cancellationToken))
|
||||
{
|
||||
scopedLogger.LogError("Could not set party loadout. Could not apply builds");
|
||||
await this.chatService.AddMessageAsync("Cannot set party loadout. Could not apply builds.", "Daybreak.API", Channel.Moderator, cancellationToken);
|
||||
await this.chatService.AddMessageAsync("Cannot set party loadout. Could not apply builds.", "Daybreak.API", Channel.CHANNEL_MODERATOR, cancellationToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
var heroBehaviorSetup = await this.gameThreadService.QueueOnGameThread(() => this.GetHeroBehaviorSetup(partyLoadout), cancellationToken);
|
||||
foreach (var heroBehaviorEntry in heroBehaviorSetup ?? [])
|
||||
foreach (var (AgentId, Behavior) in heroBehaviorSetup ?? [])
|
||||
{
|
||||
if (!await this.SetHeroBehavior(heroBehaviorEntry.AgentId, heroBehaviorEntry.Behavior, cancellationToken))
|
||||
if (!await this.SetHeroBehavior(AgentId, Behavior, cancellationToken))
|
||||
{
|
||||
scopedLogger.LogWarning("Could not set hero behavior for agent {agentId} to {behavior}", heroBehaviorEntry.AgentId, heroBehaviorEntry.Behavior);
|
||||
await this.chatService.AddMessageAsync($"Cannot set party loadout. Could not set behavior {heroBehaviorEntry.Behavior} for agent {heroBehaviorEntry.AgentId}.", "Daybreak.API", Channel.Moderator, cancellationToken);
|
||||
scopedLogger.LogWarning("Could not set hero behavior for agent {agentId} to {behavior}", AgentId, Behavior);
|
||||
await this.chatService.AddMessageAsync($"Cannot set party loadout. Could not set behavior {Behavior} for agent {AgentId}.", "Daybreak.API", Channel.CHANNEL_MODERATOR, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
await this.chatService.AddMessageAsync("Party loadout set.", "Daybreak.API", Channel.Moderator, cancellationToken);
|
||||
await this.chatService.AddMessageAsync("Party loadout set.", "Daybreak.API", Channel.CHANNEL_MODERATOR, cancellationToken);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -126,9 +128,9 @@ public sealed class PartyService(
|
||||
|
||||
var buildTuples = professions.Value.AsValueEnumerable()
|
||||
.Select(p => (p.AgentId, p, attributes.Value.FirstOrDefault(a => a.AgentId == p.AgentId), skillbars.Value.FirstOrDefault(s => s.AgentId == p.AgentId), heroFlags.Value.FirstOrDefault(f => f.AgentId == p.AgentId)))
|
||||
.Select(t => (t.AgentId, GetBuildEntryById(t.p, t.Item4, t.Item3), t.Item5.Behavior))
|
||||
.Select(t => (t.AgentId, GetBuildEntryById(t.p, t.Item4, t.Item3), t.Item5.HeroBehavior))
|
||||
.Where(t => t.Item2 is not null)
|
||||
.OfType<(uint AgentId, BuildEntry BuildEntry, Behavior Behavior)>()
|
||||
.OfType<(uint AgentId, BuildEntry BuildEntry, API.Interop.GWCA.GW.HeroBehavior Behavior)>()
|
||||
.ToList();
|
||||
|
||||
return new PartyLoadout(
|
||||
@@ -136,16 +138,17 @@ public sealed class PartyService(
|
||||
{
|
||||
if (t.AgentId == playerId)
|
||||
{
|
||||
return new PartyLoadoutEntry(0, HeroBehavior.Undefined, t.BuildEntry);
|
||||
return new PartyLoadoutEntry(0, Shared.Models.Api.HeroBehavior.Undefined, t.BuildEntry);
|
||||
}
|
||||
else if (heroes.Value.FirstOrDefault(h => h.AgentId == t.AgentId) is HeroPartyMember hero &&
|
||||
hero.AgentId == t.AgentId)
|
||||
{
|
||||
return new PartyLoadoutEntry((int)hero.HeroId, (HeroBehavior)t.Behavior, t.BuildEntry);
|
||||
return new PartyLoadoutEntry((int)hero.HeroId, (Shared.Models.Api.HeroBehavior)t.Behavior, t.BuildEntry);
|
||||
}
|
||||
|
||||
return default;
|
||||
})
|
||||
.Where(t => t is not null)
|
||||
.OfType<PartyLoadoutEntry>()]);
|
||||
}
|
||||
}, cancellationToken);
|
||||
@@ -179,7 +182,7 @@ public sealed class PartyService(
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<bool> SetHeroBehavior(uint heroAgentId, HeroBehavior behavior, CancellationToken cancellationToken)
|
||||
public async Task<bool> SetHeroBehavior(uint heroAgentId, Shared.Models.Api.HeroBehavior behavior, CancellationToken cancellationToken)
|
||||
{
|
||||
var scopedLogger = this.logger.CreateScopedLogger();
|
||||
|
||||
@@ -209,14 +212,14 @@ public sealed class PartyService(
|
||||
unsafe
|
||||
{
|
||||
var btn = this.uIContextService.GetChildFrame(frame.Frame, (uint)behavior);
|
||||
var packet = new UIPackets.MouseClick(UIPackets.MouseButtons.Left, 0, 0);
|
||||
var packet = new kMouseClick { MouseButton = 0, IsDoubleclick = 0 };
|
||||
if (btn.IsNull)
|
||||
{
|
||||
scopedLogger.LogError("Could not set hero behavior. Could not find button for behavior {behavior} in frame {frameLabel}", behavior, heroCommanderFrameLabel);
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.uIContextService.SendFrameUIMessage(btn, UIMessage.MouseClick, &packet);
|
||||
return this.uIContextService.SendFrameUIMessage(btn, UIMessage.kMouseClick, &packet);
|
||||
}
|
||||
}, cancellationToken);
|
||||
|
||||
@@ -305,7 +308,7 @@ public sealed class PartyService(
|
||||
}
|
||||
else
|
||||
{
|
||||
var hero = heroes.Value.AsValueEnumerable().FirstOrDefault(h => h.HeroId == entry.HeroId);
|
||||
var hero = heroes.Value.AsValueEnumerable().FirstOrDefault(h => (int)h.HeroId == entry.HeroId);
|
||||
return (entry, hero.AgentId);
|
||||
}
|
||||
})
|
||||
@@ -317,7 +320,7 @@ public sealed class PartyService(
|
||||
: accountContext.Pointer->UnlockedAccountSkills;
|
||||
|
||||
var unlockedProfessionsFlags = t.playerId == playerId
|
||||
? playerProfessionContext.UnlockedProfessionsFlags
|
||||
? playerProfessionContext.UnlockedProfessions
|
||||
: uint.MaxValue;
|
||||
|
||||
if (!this.buildTemplateManager.CanTemplateApply(
|
||||
@@ -325,7 +328,7 @@ public sealed class PartyService(
|
||||
(uint)t.entry.Build.Primary,
|
||||
(uint)t.entry.Build.Secondary,
|
||||
[.. t.entry.Build.Skills],
|
||||
(uint)t.Item3.CurrentPrimary,
|
||||
(uint)t.Item3.Primary,
|
||||
unlockedProfessionsFlags,
|
||||
[.. validSkills])))
|
||||
{
|
||||
@@ -358,28 +361,29 @@ public sealed class PartyService(
|
||||
continue;
|
||||
}
|
||||
|
||||
var attributeIds = new Array12Uint();
|
||||
var attributeIds = new AttributeArray12();
|
||||
var attributeValues = new Array12Uint();
|
||||
for (var i = 0; i < entry.Build.Attributes.Count && i < 12; i++)
|
||||
{
|
||||
attributeIds[i] = (uint)entry.Build.Attributes[i].Id;
|
||||
attributeIds[i] = (GWCA.GW.Constants.Attribute)entry.Build.Attributes[i].Id;
|
||||
attributeValues[i] = (uint)entry.Build.Attributes[i].BasePoints;
|
||||
}
|
||||
|
||||
var skills = new Array8Uint();
|
||||
var skills = new SkillIDArray8();
|
||||
for (var i = 0; i < entry.Build.Skills.Count && i < 8; i++)
|
||||
{
|
||||
skills[i] = entry.Build.Skills[i];
|
||||
skills[i] = (GWCA.GW.Constants.SkillID)entry.Build.Skills[i];
|
||||
}
|
||||
|
||||
var skillTemplate = new SkillTemplate(
|
||||
(uint)entry.Build.Primary,
|
||||
(uint)entry.Build.Secondary,
|
||||
(uint)entry.Build.Attributes.Count,
|
||||
attributeIds,
|
||||
attributeValues,
|
||||
skills);
|
||||
|
||||
var skillTemplate = new SkillTemplate
|
||||
{
|
||||
Primary = (GWCA.GW.Constants.Profession)entry.Build.Primary,
|
||||
Secondary = (GWCA.GW.Constants.Profession)entry.Build.Secondary,
|
||||
AttributesCount = (uint)entry.Build.Attributes.Count,
|
||||
AttributeIds = attributeIds,
|
||||
Skills = skills
|
||||
};
|
||||
Unsafe.CopyBlock(skillTemplate.AttributeValues, Unsafe.AsPointer(ref attributeValues), (uint)(12 * sizeof(uint)));
|
||||
scopedLogger.LogInformation("Applying build for agent {agentId} with primary {primary} and secondary {secondary}", agentId, entry.Build.Primary, entry.Build.Secondary);
|
||||
this.skillbarContextService.LoadBuild(agentId, &skillTemplate);
|
||||
}
|
||||
@@ -387,7 +391,7 @@ public sealed class PartyService(
|
||||
return true;
|
||||
}
|
||||
|
||||
private unsafe List<(uint AgentId, HeroBehavior Behavior)>? GetHeroBehaviorSetup(PartyLoadout partyLoadout)
|
||||
private unsafe List<(uint AgentId, Shared.Models.Api.HeroBehavior Behavior)>? GetHeroBehaviorSetup(PartyLoadout partyLoadout)
|
||||
{
|
||||
var scopedLogger = this.logger.CreateScopedLogger();
|
||||
scopedLogger.LogDebug("Getting hero behavior setup");
|
||||
@@ -402,12 +406,12 @@ public sealed class PartyService(
|
||||
return heroes.Value.AsValueEnumerable()
|
||||
.Select(h =>
|
||||
{
|
||||
if (h.HeroId is 0)
|
||||
if (h.HeroId is API.Interop.GWCA.GW.Constants.HeroID.NoHero)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var entry = partyLoadout.Entries.AsValueEnumerable().FirstOrDefault(e => (uint)e.HeroId == h.HeroId);
|
||||
var entry = partyLoadout.Entries.AsValueEnumerable().FirstOrDefault(e => e.HeroId == (int)h.HeroId);
|
||||
if (entry is null)
|
||||
{
|
||||
scopedLogger.LogWarning("No entry found for hero {heroId}", h.HeroId);
|
||||
@@ -455,21 +459,14 @@ public sealed class PartyService(
|
||||
return -1;
|
||||
}
|
||||
|
||||
var partyContext = gameContext.Pointer->PartyContext;
|
||||
if (partyContext is null)
|
||||
{
|
||||
scopedLogger.LogError("Party context is null");
|
||||
return -1;
|
||||
}
|
||||
|
||||
var charContext = gameContext.Pointer->CharContext;
|
||||
var charContext = gameContext.Pointer->Character;
|
||||
if (charContext is null)
|
||||
{
|
||||
scopedLogger.LogError("Char context is null");
|
||||
return -1;
|
||||
}
|
||||
|
||||
var playerParty = partyContext->PlayerParty;
|
||||
var playerParty = GWCA.GW.PartyMgr.GetPartyInfo(0);
|
||||
var playerId = charContext->PlayerNumber;
|
||||
var offset = 0;
|
||||
foreach(var hero in playerParty->Heroes)
|
||||
@@ -492,22 +489,22 @@ public sealed class PartyService(
|
||||
return heroNumber is -1 ? default : (uint)heroNumber;
|
||||
}
|
||||
|
||||
private static BuildEntry? GetBuildEntryById(ProfessionsContext professionContext, SkillbarContext skillbar, PartyAttribute attributes)
|
||||
private static BuildEntry? GetBuildEntryById(ProfessionState professionContext, SkillbarData skillbar, PartyAttribute attributes)
|
||||
{
|
||||
return new BuildEntry(
|
||||
Primary: (int)professionContext.CurrentPrimary,
|
||||
Secondary: (int)professionContext.CurrentSecondary,
|
||||
Attributes: attributes.Attributes.GetAttributeEntryList(),
|
||||
Primary: (int)professionContext.Primary,
|
||||
Secondary: (int)professionContext.Secondary,
|
||||
Attributes: attributes.Attribute.GetAttributeEntryList().ToList(),
|
||||
Skills:
|
||||
[
|
||||
skillbar.Skill0.Id,
|
||||
skillbar.Skill1.Id,
|
||||
skillbar.Skill2.Id,
|
||||
skillbar.Skill3.Id,
|
||||
skillbar.Skill4.Id,
|
||||
skillbar.Skill5.Id,
|
||||
skillbar.Skill6.Id,
|
||||
skillbar.Skill7.Id
|
||||
(uint)skillbar.Skills[0].SkillId,
|
||||
(uint)skillbar.Skills[1].SkillId,
|
||||
(uint)skillbar.Skills[2].SkillId,
|
||||
(uint)skillbar.Skills[3].SkillId,
|
||||
(uint)skillbar.Skills[4].SkillId,
|
||||
(uint)skillbar.Skills[5].SkillId,
|
||||
(uint)skillbar.Skills[6].SkillId,
|
||||
(uint)skillbar.Skills[7].SkillId
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Daybreak.API.Interop;
|
||||
using Daybreak.API.Interop.GuildWars;
|
||||
using Daybreak.API.Models;
|
||||
using Daybreak.API.Services.Interop;
|
||||
using System.Extensions.Core;
|
||||
|
||||
@@ -20,7 +19,7 @@ public sealed class UIService(
|
||||
var scopedLogger = this.logger.CreateScopedLogger();
|
||||
var keyDownResult = await this.gameThreadService.QueueOnGameThread(() =>
|
||||
{
|
||||
if (!this.uIContextService.KeyDown(action, frame))
|
||||
if (!this.uIContextService.KeyDown((GWCA.GW.UI.ControlAction)action, frame))
|
||||
{
|
||||
scopedLogger.LogError("Failed to send keydown action {action}", action);
|
||||
return false;
|
||||
@@ -36,7 +35,7 @@ public sealed class UIService(
|
||||
|
||||
var keyUpResult = await this.gameThreadService.QueueOnGameThread(() =>
|
||||
{
|
||||
if (!this.uIContextService.KeyUp(action, frame))
|
||||
if (!this.uIContextService.KeyUp((GWCA.GW.UI.ControlAction)action, frame))
|
||||
{
|
||||
scopedLogger.LogError("Failed to send keyup action {action}", action);
|
||||
return false;
|
||||
@@ -86,7 +85,7 @@ public sealed class UIService(
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<string?> DecodeString(string encoded, Language language, CancellationToken cancellationToken)
|
||||
public async Task<string?> DecodeString(string encoded, GWCA.GW.Constants.Language language, CancellationToken cancellationToken)
|
||||
{
|
||||
// GWCA's AsyncDecodeStr handles language switching internally (sets language, decodes, restores)
|
||||
return await this.uIContextService.AsyncDecodeStringAsync(encoded, language, cancellationToken);
|
||||
@@ -96,14 +95,14 @@ public sealed class UIService(
|
||||
{
|
||||
return frameLabel switch
|
||||
{
|
||||
"AgentCommander0" => ControlAction.OpenHeroCommander1,
|
||||
"AgentCommander1" => ControlAction.OpenHeroCommander2,
|
||||
"AgentCommander2" => ControlAction.OpenHeroCommander3,
|
||||
"AgentCommander3" => ControlAction.OpenHeroCommander4,
|
||||
"AgentCommander4" => ControlAction.OpenHeroCommander5,
|
||||
"AgentCommander5" => ControlAction.OpenHeroCommander6,
|
||||
"AgentCommander6" => ControlAction.OpenHeroCommander7,
|
||||
_ => ControlAction.None
|
||||
"AgentCommander0" => ControlAction.ControlAction_OpenHeroCommander1,
|
||||
"AgentCommander1" => ControlAction.ControlAction_OpenHeroCommander2,
|
||||
"AgentCommander2" => ControlAction.ControlAction_OpenHeroCommander3,
|
||||
"AgentCommander3" => ControlAction.ControlAction_OpenHeroCommander4,
|
||||
"AgentCommander4" => ControlAction.ControlAction_OpenHeroCommander5,
|
||||
"AgentCommander5" => ControlAction.ControlAction_OpenHeroCommander6,
|
||||
"AgentCommander6" => ControlAction.ControlAction_OpenHeroCommander7,
|
||||
_ => ControlAction.ControlAction_None
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Daybreak.API.Services.Interop;
|
||||
using Daybreak.Shared.Services.BuildTemplates;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Daybreak.Shared.Services.BuildTemplates.Parsers;
|
||||
|
||||
namespace Daybreak.API.Services;
|
||||
|
||||
@@ -8,6 +8,9 @@ public static class WebApplicationBuilderExtensions
|
||||
{
|
||||
public static WebApplicationBuilder WithDaybreakServices(this WebApplicationBuilder builder)
|
||||
{
|
||||
builder.Services.AddSingleton<ITemplateParser, LegacySkillTemplateParser>();
|
||||
builder.Services.AddSingleton<ITemplateParser, SkillTemplateParser>();
|
||||
builder.Services.AddSingleton<ITemplateParser, PartyLoadoutTemplateParser>();
|
||||
builder.Services.AddSingleton<IBuildTemplateManager, BuildTemplateManager>();
|
||||
builder.Services.AddSingleton<MemoryScanningService>();
|
||||
builder.Services.AddSingleton<ChatService>();
|
||||
|
||||
@@ -488,7 +488,6 @@ public sealed class FocusViewModel(
|
||||
}
|
||||
|
||||
if (this.BuildComponentContext?.CharacterUnlockedSkills.SequenceEqual(mainPlayerBuildContext.UnlockedCharacterSkills) is true &&
|
||||
this.BuildComponentContext?.AccountUnlockedSkills.SequenceEqual(mainPlayerBuildContext.UnlockedAccountSkills) is true &&
|
||||
this.BuildComponentContext?.UnlockedProfessions == mainPlayerBuildContext.UnlockedProfessions &&
|
||||
this.BuildComponentContext?.PrimaryProfessionId == mainPlayerBuildContext.PrimaryProfessionId &&
|
||||
DateTime.Now < this.lastBuildCheck + BuildsCheckFrequency)
|
||||
@@ -518,7 +517,6 @@ public sealed class FocusViewModel(
|
||||
{
|
||||
IsInOutpost = instanceInfo.Type is Shared.Models.Api.InstanceType.Outpost,
|
||||
PrimaryProfessionId = mainPlayerBuildContext.PrimaryProfessionId,
|
||||
AccountUnlockedSkills = mainPlayerBuildContext.UnlockedAccountSkills,
|
||||
CharacterUnlockedSkills = mainPlayerBuildContext.UnlockedCharacterSkills,
|
||||
UnlockedProfessions = mainPlayerBuildContext.UnlockedProfessions,
|
||||
AvailableBuilds = matchingBuilds
|
||||
|
||||
@@ -0,0 +1,863 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using static Daybreak.Generators.GenerateGWCABindings;
|
||||
|
||||
namespace Daybreak.Generators;
|
||||
|
||||
internal static class CppHeaderParser
|
||||
{
|
||||
// ════════════════════════════════════════════════════════════════
|
||||
// Regex patterns for enum parsing
|
||||
// ════════════════════════════════════════════════════════════════
|
||||
|
||||
// Matches: enum class Name : Type {
|
||||
// Matches: enum class Name {
|
||||
// Matches: enum Name : Type {
|
||||
// Matches: enum {
|
||||
private static readonly Regex EnumStartRegex = new(
|
||||
@"^\s*enum\s+(?:class\s+)?(?:(\w+)\s*)?(?::\s*(\w+)\s*)?\{",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches: enum class Name : Type (brace on next line)
|
||||
// Matches: enum class Name (brace on next line)
|
||||
// Does NOT match forward declarations ending with ;
|
||||
private static readonly Regex EnumNobraceRegex = new(
|
||||
@"^\s*enum\s+(?:class\s+)?(?:(\w+)\s*)?(?::\s*(\w+)\s*)?$",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// ════════════════════════════════════════════════════════════════
|
||||
// Regex patterns for struct parsing
|
||||
// ════════════════════════════════════════════════════════════════
|
||||
|
||||
// Matches: struct Name { or struct Name : public Base { or struct Name : Base {
|
||||
// Captures: Name, optional BaseType
|
||||
private static readonly Regex StructStartRegex = new(
|
||||
@"^\s*struct\s+(\w+)\s*(?::\s*(?:public\s+)?(\w+(?:::\w+)*)\s*)?\{",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches: struct Name : public Base (brace on next line)
|
||||
private static readonly Regex StructNobraceRegex = new(
|
||||
@"^\s*struct\s+(\w+)\s*(?::\s*(?:public\s+)?(\w+(?:::\w+)*)\s*)?$",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches field with offset comment: /* +h0024 */ Type field;
|
||||
private static readonly Regex FieldWithOffsetRegex = new(
|
||||
@"^\s*/\*\s*\+h([0-9A-Fa-f]{4})\s*\*/\s*(.+?)\s*;\s*(?://\s*(.*))?$",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches field without offset comment: Type field;
|
||||
// Also handles inline initializers like = value or {} or {value}
|
||||
private static readonly Regex FieldNoOffsetRegex = new(
|
||||
@"^\s*(?!(?:inline|static|virtual|GWCA_API|typedef|using|enum|struct|union|return|if|for|while|switch|\[\[|\}))([A-Za-z_][\w:*&<>\s,]+?)\s+(\w+)(?:\s*\[\s*([^\]]+)\s*\])?(?:\s*\{[^}]*\})?(?:\s*=\s*[^;]+)?\s*;\s*(?://\s*(.*))?$",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches static_assert(sizeof(Name) == 0xHEX or decimal)
|
||||
private static readonly Regex SizeofAssertRegex = new(
|
||||
@"static_assert\s*\(\s*sizeof\s*\(\s*(\w+)\s*\)\s*==\s*(0x[0-9A-Fa-f]+|\d+)",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// ════════════════════════════════════════════════════════════════
|
||||
// Other patterns
|
||||
// ════════════════════════════════════════════════════════════════
|
||||
|
||||
// Matches: constexpr Type Name = Value; // comment
|
||||
private static readonly Regex ConstexprRegex = new(
|
||||
@"^\s*constexpr\s+(\w+)\s+(\w+)\s*=\s*(.+?)\s*;\s*(?://\s*(.*))?$",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches: namespace Name {
|
||||
// Also matches: namespace Name1::Name2 { (but we split on ::)
|
||||
private static readonly Regex NamespaceRegex = new(
|
||||
@"^\s*namespace\s+([\w:]+)\s*\{",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches closing brace with optional semicolon
|
||||
private static readonly Regex CloseBraceRegex = new(
|
||||
@"^\s*\}\s*;?\s*$",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches: typedef ... (to skip)
|
||||
private static readonly Regex TypedefRegex = new(
|
||||
@"^\s*typedef\s+",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches lines to skip inside structs
|
||||
private static readonly Regex SkipLineRegex = new(
|
||||
@"^\s*(inline|static\s+const|GWCA_API|virtual|explicit|friend|\[\[nodiscard\]\]|constexpr|template\s*<|//|#|public:|private:|protected:|$)",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches: union { (to skip union blocks)
|
||||
private static readonly Regex UnionStartRegex = new(
|
||||
@"^\s*union\s*\{",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches: template<...> struct/class (to skip)
|
||||
private static readonly Regex TemplateStructRegex = new(
|
||||
@"^\s*template\s*<",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches inline function definitions (static, inline, GWCA_API, etc.) that have a body
|
||||
private static readonly Regex FunctionWithBodyRegex = new(
|
||||
@"^\s*(?:static|inline|GWCA_API|virtual|explicit|constexpr).*\([^)]*\)\s*(?:const)?\s*\{",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches function declarations with body on next line (no opening brace)
|
||||
private static readonly Regex FunctionNoBraceRegex = new(
|
||||
@"^\s*(?:static|inline|GWCA_API|virtual|explicit|constexpr).*\([^)]*\)\s*(?:const)?\s*$",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches out-of-line method definitions: Type* Class::Method() { or Type Class::Method() const {
|
||||
private static readonly Regex OutOfLineMethodRegex = new(
|
||||
@"^\s*(?:const\s+)?[\w:*&<>]+(?:\s+[\w:*&<>]+)*\s+\w+::\w+\s*\([^)]*\)\s*(?:const)?\s*\{",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// Matches standalone opening brace
|
||||
private static readonly Regex OpenBraceOnlyRegex = new(
|
||||
@"^\s*\{\s*$",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
public static List<string> DebugLines { get; } = [];
|
||||
|
||||
public static void Parse(string headerText, ConstantsNode root)
|
||||
{
|
||||
var lines = headerText.Split('\n');
|
||||
var namespaceStack = new Stack<ConstantsNode>();
|
||||
namespaceStack.Push(root);
|
||||
|
||||
// Parsing state
|
||||
bool inEnum = false;
|
||||
CppEnumDef? currentEnum = null;
|
||||
bool inStruct = false;
|
||||
CppStructDef? currentStruct = null;
|
||||
int structBraceDepth = 0;
|
||||
bool inSkipBlock = false;
|
||||
int skipBlockBraceCount = 0;
|
||||
bool inMultiLineConstexpr = false;
|
||||
int multiLineBraceCount = 0;
|
||||
int freeBraceDepth = 0; // Track braces from functions with body on separate line
|
||||
|
||||
// Track struct sizes from static_assert
|
||||
var structSizes = new Dictionary<string, int>(StringComparer.Ordinal);
|
||||
|
||||
// First pass: collect sizeof assertions
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var sizeMatch = SizeofAssertRegex.Match(line);
|
||||
if (sizeMatch.Success)
|
||||
{
|
||||
var name = sizeMatch.Groups[1].Value;
|
||||
var sizeStr = sizeMatch.Groups[2].Value;
|
||||
int size = sizeStr.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
|
||||
? Convert.ToInt32(sizeStr, 16)
|
||||
: int.Parse(sizeStr);
|
||||
structSizes[name] = size;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
var line = lines[i].TrimEnd('\r');
|
||||
|
||||
// Skip preprocessor directives
|
||||
if (line.TrimStart().StartsWith("#"))
|
||||
continue;
|
||||
|
||||
var trimmed = line.TrimStart();
|
||||
if (trimmed.Length == 0)
|
||||
continue;
|
||||
if (trimmed.StartsWith("//") && !inEnum && !inStruct)
|
||||
continue;
|
||||
|
||||
// Handle multi-line constexpr (like constexpr std::array)
|
||||
if (inMultiLineConstexpr)
|
||||
{
|
||||
multiLineBraceCount += CountChar(line, '{') - CountChar(line, '}');
|
||||
if (multiLineBraceCount <= 0 || line.TrimEnd().EndsWith(";"))
|
||||
{
|
||||
inMultiLineConstexpr = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle skip blocks (unions, template structs, etc.)
|
||||
if (inSkipBlock)
|
||||
{
|
||||
skipBlockBraceCount += CountChar(line, '{') - CountChar(line, '}');
|
||||
if (skipBlockBraceCount <= 0)
|
||||
{
|
||||
inSkipBlock = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Inside an enum body (multi-line) ───────────────────
|
||||
if (inEnum && currentEnum is not null)
|
||||
{
|
||||
if (trimmed.StartsWith("//"))
|
||||
continue;
|
||||
|
||||
// Strip comments before checking for closing brace - comments can contain braces like "{ wchar_t* title }"
|
||||
var trimmedWithoutComment = trimmed;
|
||||
var commentIdx = trimmed.IndexOf("//");
|
||||
if (commentIdx >= 0)
|
||||
trimmedWithoutComment = trimmed.Substring(0, commentIdx).TrimEnd();
|
||||
|
||||
var closeBraceIdx = trimmedWithoutComment.IndexOf('}');
|
||||
if (closeBraceIdx >= 0)
|
||||
{
|
||||
if (closeBraceIdx > 0)
|
||||
{
|
||||
ParseEnumMembersFromLine(trimmed.Substring(0, closeBraceIdx), currentEnum);
|
||||
}
|
||||
inEnum = false;
|
||||
var node = namespaceStack.Peek();
|
||||
node.Enums.Add(currentEnum);
|
||||
currentEnum = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
ParseEnumMembersFromLine(trimmed, currentEnum);
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Inside a struct body ───────────────────────────────
|
||||
if (inStruct && currentStruct is not null)
|
||||
{
|
||||
// Strip comments before counting braces - comments can contain braces
|
||||
var lineWithoutComments = StripComments(line);
|
||||
int openBraces = CountChar(lineWithoutComments, '{');
|
||||
int closeBraces = CountChar(lineWithoutComments, '}');
|
||||
int prevDepth = structBraceDepth;
|
||||
structBraceDepth += openBraces - closeBraces;
|
||||
|
||||
// Debug: Track brace changes for AgentLiving
|
||||
if (currentStruct.Name == "AgentLiving" && (openBraces > 0 || closeBraces > 0))
|
||||
{
|
||||
DebugLines.Add($"[BRACE] line {i+1}: {currentStruct.Name} depth {prevDepth}->{structBraceDepth} (open={openBraces}, close={closeBraces})");
|
||||
}
|
||||
|
||||
// If we hit the closing brace of the struct
|
||||
if (structBraceDepth <= 0)
|
||||
{
|
||||
// Apply known size if available
|
||||
if (structSizes.TryGetValue(currentStruct.Name, out var size))
|
||||
currentStruct.Size = size;
|
||||
|
||||
var node = namespaceStack.Peek();
|
||||
// Debug: capture namespace path
|
||||
var pathParts = new List<string>();
|
||||
foreach (var n in namespaceStack)
|
||||
pathParts.Add(n.Name);
|
||||
pathParts.Reverse();
|
||||
currentStruct.DebugNamespacePath = string.Join(".", pathParts);
|
||||
|
||||
DebugLines.Add($"[STRUCT-END] line {i+1}: {currentStruct.Name} with {currentStruct.Fields.Count} fields");
|
||||
node.Structs.Add(currentStruct);
|
||||
currentStruct = null;
|
||||
inStruct = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip nested named structs (e.g., "struct Foo {") but NOT anonymous unions/structs
|
||||
// We want to parse fields inside unions because they map to overlapping [FieldOffset] in C#
|
||||
// Only skip if we're inside a named nested struct (not an anonymous union/struct block)
|
||||
if (structBraceDepth > 1)
|
||||
{
|
||||
// Still try to parse fields with explicit offsets inside unions
|
||||
// These are perfectly valid - they become overlapping fields in C# explicit layout
|
||||
var fieldOffsetMatchNested = FieldWithOffsetRegex.Match(trimmed);
|
||||
if (fieldOffsetMatchNested.Success)
|
||||
{
|
||||
var offset = Convert.ToInt32(fieldOffsetMatchNested.Groups[1].Value, 16);
|
||||
var typeAndName = fieldOffsetMatchNested.Groups[2].Value;
|
||||
var comment = fieldOffsetMatchNested.Groups[3].Success ? fieldOffsetMatchNested.Groups[3].Value.Trim() : null;
|
||||
|
||||
var field = ParseFieldTypeAndName(typeAndName, offset, comment);
|
||||
if (field is not null)
|
||||
currentStruct.Fields.Add(field);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip comment-only lines
|
||||
if (trimmed.StartsWith("//"))
|
||||
continue;
|
||||
|
||||
// Skip method/static/inline lines
|
||||
if (SkipLineRegex.IsMatch(trimmed))
|
||||
continue;
|
||||
|
||||
// Skip lines with function bodies or method declarations
|
||||
// Strip trailing // comment before checking - comments can contain parentheses like "(runes,pcons,etc)"
|
||||
var trimmedWithoutTrailingComment = trimmed;
|
||||
var trailingCommentIdx = trimmed.IndexOf("//");
|
||||
if (trailingCommentIdx > 0)
|
||||
trimmedWithoutTrailingComment = trimmed.Substring(0, trailingCommentIdx).TrimEnd();
|
||||
|
||||
if (trimmedWithoutTrailingComment.Contains("(") && (trimmedWithoutTrailingComment.Contains(")") || trimmedWithoutTrailingComment.Contains("{")))
|
||||
continue;
|
||||
|
||||
// Skip bitfield declarations (e.g., DyeColor dye1 : 4;)
|
||||
if (trimmed.Contains(" : ") && Regex.IsMatch(trimmed, @":\s*\d+\s*;"))
|
||||
continue;
|
||||
|
||||
// Skip union starts
|
||||
if (UnionStartRegex.IsMatch(trimmed))
|
||||
continue;
|
||||
|
||||
// Try to parse field with offset
|
||||
var fieldOffsetMatch = FieldWithOffsetRegex.Match(trimmed);
|
||||
if (fieldOffsetMatch.Success)
|
||||
{
|
||||
var offset = Convert.ToInt32(fieldOffsetMatch.Groups[1].Value, 16);
|
||||
var typeAndName = fieldOffsetMatch.Groups[2].Value;
|
||||
var comment = fieldOffsetMatch.Groups[3].Success ? fieldOffsetMatch.Groups[3].Value.Trim() : null;
|
||||
|
||||
var field = ParseFieldTypeAndName(typeAndName, offset, comment);
|
||||
if (field is not null)
|
||||
currentStruct.Fields.Add(field);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try to parse field without offset
|
||||
var fieldNoOffsetMatch = FieldNoOffsetRegex.Match(trimmed);
|
||||
if (fieldNoOffsetMatch.Success)
|
||||
{
|
||||
var cppType = fieldNoOffsetMatch.Groups[1].Value.Trim();
|
||||
var name = fieldNoOffsetMatch.Groups[2].Value;
|
||||
var arraySize = fieldNoOffsetMatch.Groups[3].Success ? fieldNoOffsetMatch.Groups[3].Value.Trim() : null;
|
||||
var comment = fieldNoOffsetMatch.Groups[4].Success ? fieldNoOffsetMatch.Groups[4].Value.Trim() : null;
|
||||
|
||||
var field = new CppStructField
|
||||
{
|
||||
Name = name,
|
||||
CppType = cppType,
|
||||
ArraySize = arraySize,
|
||||
Comment = comment,
|
||||
};
|
||||
currentStruct.Fields.Add(field);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Try to match namespace ─────────────────────────────
|
||||
var nsMatch = NamespaceRegex.Match(trimmed);
|
||||
if (nsMatch.Success)
|
||||
{
|
||||
var nsName = nsMatch.Groups[1].Value;
|
||||
var parts = nsName.Split(new[] { "::" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var part in parts)
|
||||
{
|
||||
var current = namespaceStack.Peek();
|
||||
var child = current.GetOrCreateChild(part);
|
||||
namespaceStack.Push(child);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Closing brace (function body end or namespace end) ─
|
||||
if (CloseBraceRegex.IsMatch(trimmed))
|
||||
{
|
||||
// If we have unclosed function bodies, close those first
|
||||
if (freeBraceDepth > 0)
|
||||
{
|
||||
freeBraceDepth--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (namespaceStack.Count > 1)
|
||||
{
|
||||
// Debug: Track where namespace was popped
|
||||
var poppedNode = namespaceStack.Pop();
|
||||
poppedNode.DebugPopLine = i + 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Skip static_assert ─────────────────────────────────
|
||||
if (trimmed.StartsWith("static_assert"))
|
||||
{
|
||||
if (!trimmed.Contains(";"))
|
||||
{
|
||||
for (int j = i + 1; j < lines.Length; j++)
|
||||
{
|
||||
if (lines[j].Contains(";"))
|
||||
{
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Handle typedef struct Name { (parse as regular struct) ─
|
||||
var typedefStructMatch = Regex.Match(trimmed, @"^\s*typedef\s+struct\s+(\w+)\s*\{");
|
||||
if (typedefStructMatch.Success)
|
||||
{
|
||||
var structName = typedefStructMatch.Groups[1].Value;
|
||||
currentStruct = new CppStructDef
|
||||
{
|
||||
Name = structName,
|
||||
};
|
||||
inStruct = true;
|
||||
structBraceDepth = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Handle typedef Array<T> AliasName; ───────────────────────
|
||||
var typedefArrayMatch = Regex.Match(trimmed, @"^\s*typedef\s+(\w+)\s*<\s*([\w:\s*]+)\s*>\s+(\w+)\s*;");
|
||||
if (typedefArrayMatch.Success)
|
||||
{
|
||||
var sourceType = typedefArrayMatch.Groups[1].Value;
|
||||
var templateArg = typedefArrayMatch.Groups[2].Value.Trim();
|
||||
var aliasName = typedefArrayMatch.Groups[3].Value;
|
||||
namespaceStack.Peek().TypeAliases.Add(new CppTypeAlias
|
||||
{
|
||||
AliasName = aliasName,
|
||||
SourceType = sourceType,
|
||||
TemplateArg = templateArg
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Skip other typedef ─────────────────────────────────
|
||||
if (TypedefRegex.IsMatch(trimmed))
|
||||
continue;
|
||||
|
||||
// ── Skip template struct/class ─────────────────────────
|
||||
if (TemplateStructRegex.IsMatch(trimmed))
|
||||
{
|
||||
int braces = CountChar(trimmed, '{') - CountChar(trimmed, '}');
|
||||
if (braces > 0)
|
||||
{
|
||||
inSkipBlock = true;
|
||||
skipBlockBraceCount = braces;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Skip inline function bodies ────────────────────────
|
||||
if (FunctionWithBodyRegex.IsMatch(trimmed))
|
||||
{
|
||||
int braces = CountChar(trimmed, '{') - CountChar(trimmed, '}');
|
||||
if (braces > 0)
|
||||
{
|
||||
inSkipBlock = true;
|
||||
skipBlockBraceCount = braces;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Skip out-of-line method definitions (Type* Class::Method() {) ─
|
||||
if (OutOfLineMethodRegex.IsMatch(trimmed))
|
||||
{
|
||||
int braces = CountChar(trimmed, '{') - CountChar(trimmed, '}');
|
||||
DebugLines.Add($"[OUT-OF-LINE] line {i+1}: {trimmed.Substring(0, Math.Min(50, trimmed.Length))}... braces={braces}");
|
||||
if (braces > 0)
|
||||
{
|
||||
inSkipBlock = true;
|
||||
skipBlockBraceCount = braces;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (trimmed.Contains("::") && trimmed.Contains("(") && trimmed.Contains("{"))
|
||||
{
|
||||
DebugLines.Add($"[UNMATCHED-METHOD] line {i+1}: {trimmed.Substring(0, Math.Min(60, trimmed.Length))}");
|
||||
}
|
||||
|
||||
// ── Track function declarations with body on separate line ─
|
||||
if (FunctionNoBraceRegex.IsMatch(trimmed))
|
||||
{
|
||||
// The next meaningful line should be { which starts the body
|
||||
// We'll handle this by looking for standalone { and tracking brace depth
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Track standalone opening braces (function bodies with { on separate line)
|
||||
if (OpenBraceOnlyRegex.IsMatch(trimmed))
|
||||
{
|
||||
freeBraceDepth++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Skip constexpr std::array etc. ─────────────────────
|
||||
if (trimmed.StartsWith("constexpr std::"))
|
||||
{
|
||||
int braces = CountChar(trimmed, '{') - CountChar(trimmed, '}');
|
||||
if (braces > 0)
|
||||
{
|
||||
inMultiLineConstexpr = true;
|
||||
multiLineBraceCount = braces;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Try to match struct start ──────────────────────────
|
||||
var structMatch = StructStartRegex.Match(trimmed);
|
||||
if (structMatch.Success)
|
||||
{
|
||||
var structName = structMatch.Groups[1].Value;
|
||||
var baseType = structMatch.Groups[2].Success ? structMatch.Groups[2].Value : null;
|
||||
DebugLines.Add($"[STRUCT-START] line {i+1}: {structName} (inSkip={inSkipBlock}, freeBrace={freeBraceDepth})");
|
||||
|
||||
// Skip some special cases
|
||||
if (structName.StartsWith("__") || structName == "Packet")
|
||||
{
|
||||
int braces = CountChar(trimmed, '{') - CountChar(trimmed, '}');
|
||||
if (braces > 0)
|
||||
{
|
||||
inSkipBlock = true;
|
||||
skipBlockBraceCount = braces;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
currentStruct = new CppStructDef
|
||||
{
|
||||
Name = structName,
|
||||
BaseType = baseType,
|
||||
};
|
||||
inStruct = true;
|
||||
structBraceDepth = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Struct without opening brace on same line ──────────
|
||||
var structNobraceMatch = StructNobraceRegex.Match(trimmed);
|
||||
if (structNobraceMatch.Success)
|
||||
{
|
||||
var structName = structNobraceMatch.Groups[1].Value;
|
||||
|
||||
// Skip forward declarations (just struct Name;)
|
||||
if (trimmed.EndsWith(";"))
|
||||
continue;
|
||||
|
||||
// Skip special cases
|
||||
if (structName.StartsWith("__") || structName == "Packet")
|
||||
continue;
|
||||
|
||||
// Look ahead for opening brace
|
||||
for (int j = i + 1; j < lines.Length; j++)
|
||||
{
|
||||
var nextTrimmed = lines[j].TrimStart().TrimEnd('\r');
|
||||
if (nextTrimmed.Length == 0 || nextTrimmed.StartsWith("//"))
|
||||
continue;
|
||||
|
||||
if (nextTrimmed.Contains("{"))
|
||||
{
|
||||
var baseType = structNobraceMatch.Groups[2].Success ? structNobraceMatch.Groups[2].Value : null;
|
||||
currentStruct = new CppStructDef
|
||||
{
|
||||
Name = structName,
|
||||
BaseType = baseType,
|
||||
};
|
||||
inStruct = true;
|
||||
structBraceDepth = 1;
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
break; // unexpected content
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Try to match enum start (with opening brace on same line) ──
|
||||
var enumMatch = EnumStartRegex.Match(trimmed);
|
||||
if (enumMatch.Success)
|
||||
{
|
||||
var enumDef = new CppEnumDef
|
||||
{
|
||||
Name = enumMatch.Groups[1].Success && enumMatch.Groups[1].Value.Length > 0
|
||||
? enumMatch.Groups[1].Value : null,
|
||||
UnderlyingType = enumMatch.Groups[2].Success && enumMatch.Groups[2].Value.Length > 0
|
||||
? enumMatch.Groups[2].Value : null,
|
||||
};
|
||||
|
||||
var afterBrace = trimmed.Substring(enumMatch.Length);
|
||||
var closeBraceIdx = afterBrace.IndexOf('}');
|
||||
|
||||
if (closeBraceIdx >= 0)
|
||||
{
|
||||
var body = afterBrace.Substring(0, closeBraceIdx);
|
||||
ParseEnumMembersFromLine(body, enumDef);
|
||||
var node = namespaceStack.Peek();
|
||||
node.Enums.Add(enumDef);
|
||||
}
|
||||
else
|
||||
{
|
||||
var rest = afterBrace.Trim();
|
||||
if (rest.Length > 0)
|
||||
{
|
||||
ParseEnumMembersFromLine(rest, enumDef);
|
||||
}
|
||||
currentEnum = enumDef;
|
||||
inEnum = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Enum without opening brace on same line ────────────
|
||||
var enumNobraceMatch = EnumNobraceRegex.Match(trimmed);
|
||||
if (enumNobraceMatch.Success)
|
||||
{
|
||||
for (int j = i + 1; j < lines.Length; j++)
|
||||
{
|
||||
var nextTrimmed = lines[j].TrimStart().TrimEnd('\r');
|
||||
if (nextTrimmed.Length == 0 || nextTrimmed.StartsWith("//"))
|
||||
continue;
|
||||
|
||||
if (nextTrimmed.Contains("{"))
|
||||
{
|
||||
var enumDef = new CppEnumDef
|
||||
{
|
||||
Name = enumNobraceMatch.Groups[1].Success && enumNobraceMatch.Groups[1].Value.Length > 0
|
||||
? enumNobraceMatch.Groups[1].Value : null,
|
||||
UnderlyingType = enumNobraceMatch.Groups[2].Success && enumNobraceMatch.Groups[2].Value.Length > 0
|
||||
? enumNobraceMatch.Groups[2].Value : null,
|
||||
};
|
||||
|
||||
var braceIdx = nextTrimmed.IndexOf('{');
|
||||
var afterBrace = nextTrimmed.Substring(braceIdx + 1);
|
||||
var closeBraceIdx = afterBrace.IndexOf('}');
|
||||
|
||||
if (closeBraceIdx >= 0)
|
||||
{
|
||||
var body = afterBrace.Substring(0, closeBraceIdx);
|
||||
ParseEnumMembersFromLine(body, enumDef);
|
||||
var node = namespaceStack.Peek();
|
||||
node.Enums.Add(enumDef);
|
||||
}
|
||||
else
|
||||
{
|
||||
var rest = afterBrace.Trim();
|
||||
if (rest.Length > 0)
|
||||
{
|
||||
ParseEnumMembersFromLine(rest, enumDef);
|
||||
}
|
||||
currentEnum = enumDef;
|
||||
inEnum = true;
|
||||
}
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
break; // unexpected content
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Try to match constexpr field ───────────────────────
|
||||
var constMatch = ConstexprRegex.Match(trimmed);
|
||||
if (constMatch.Success)
|
||||
{
|
||||
var cppType = constMatch.Groups[1].Value;
|
||||
var name = constMatch.Groups[2].Value;
|
||||
var value = constMatch.Groups[3].Value.Trim();
|
||||
var comment = constMatch.Groups[4].Success ? constMatch.Groups[4].Value.Trim() : null;
|
||||
|
||||
// Skip complex expressions with :: references or casts
|
||||
if (value.Contains("::") || value.Contains("(") || value.Contains("static_cast"))
|
||||
continue;
|
||||
|
||||
var field = new CppConstField
|
||||
{
|
||||
Name = name,
|
||||
CppType = cppType,
|
||||
Value = NormalizeCppValue(value),
|
||||
Comment = comment,
|
||||
};
|
||||
var node = namespaceStack.Peek();
|
||||
node.Constants.Add(field);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a combined "Type Name" or "Type Name[Size]" string into a field.
|
||||
/// </summary>
|
||||
private static CppStructField? ParseFieldTypeAndName(string typeAndName, int offset, string? comment)
|
||||
{
|
||||
typeAndName = typeAndName.Trim();
|
||||
|
||||
// Handle array notation: uint32_t name[7]
|
||||
string? arraySize = null;
|
||||
var bracketIdx = typeAndName.IndexOf('[');
|
||||
if (bracketIdx >= 0)
|
||||
{
|
||||
var closeBracket = typeAndName.IndexOf(']', bracketIdx);
|
||||
if (closeBracket > bracketIdx)
|
||||
{
|
||||
arraySize = typeAndName.Substring(bracketIdx + 1, closeBracket - bracketIdx - 1).Trim();
|
||||
typeAndName = typeAndName.Substring(0, bracketIdx).Trim();
|
||||
}
|
||||
}
|
||||
|
||||
// Split type and name - name is the last token
|
||||
var tokens = typeAndName.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (tokens.Length < 2)
|
||||
return null;
|
||||
|
||||
var name = tokens[tokens.Length - 1].TrimStart('*');
|
||||
var cppType = string.Join(" ", tokens.Take(tokens.Length - 1));
|
||||
|
||||
// Handle pointer attached to name: Item *weapon -> Item*, weapon
|
||||
if (tokens[tokens.Length - 1].StartsWith("*"))
|
||||
{
|
||||
cppType += "*";
|
||||
}
|
||||
// Handle pointer attached to type: Item* weapon
|
||||
else if (cppType.EndsWith("*"))
|
||||
{
|
||||
// Already correct
|
||||
}
|
||||
// Handle pointer in middle: Item * weapon
|
||||
else if (tokens.Any(t => t == "*"))
|
||||
{
|
||||
cppType = cppType.Replace(" *", "*").Replace("* ", "*");
|
||||
if (!cppType.EndsWith("*"))
|
||||
cppType += "*";
|
||||
}
|
||||
|
||||
return new CppStructField
|
||||
{
|
||||
Name = name,
|
||||
CppType = cppType.Trim(),
|
||||
Offset = offset,
|
||||
ArraySize = arraySize,
|
||||
Comment = comment,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses comma-separated enum members from a single line of text.
|
||||
/// </summary>
|
||||
private static void ParseEnumMembersFromLine(string line, CppEnumDef enumDef)
|
||||
{
|
||||
string? lineComment = null;
|
||||
var commentIdx = line.IndexOf("//");
|
||||
if (commentIdx >= 0)
|
||||
{
|
||||
lineComment = line.Substring(commentIdx + 2).Trim();
|
||||
line = line.Substring(0, commentIdx);
|
||||
}
|
||||
|
||||
var parts = line.Split(',');
|
||||
CppEnumMember? lastMember = null;
|
||||
|
||||
foreach (var part in parts)
|
||||
{
|
||||
var trimPart = part.Trim();
|
||||
if (trimPart.Length == 0)
|
||||
continue;
|
||||
|
||||
var eqIdx = trimPart.IndexOf('=');
|
||||
string name;
|
||||
string? value = null;
|
||||
|
||||
if (eqIdx >= 0)
|
||||
{
|
||||
name = trimPart.Substring(0, eqIdx).Trim();
|
||||
value = trimPart.Substring(eqIdx + 1).Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
name = trimPart;
|
||||
}
|
||||
|
||||
if (name.Length > 0 && (char.IsLetter(name[0]) || name[0] == '_'))
|
||||
{
|
||||
var member = new CppEnumMember
|
||||
{
|
||||
Name = name,
|
||||
Value = value,
|
||||
};
|
||||
enumDef.Members.Add(member);
|
||||
lastMember = member;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastMember is not null && lineComment is not null)
|
||||
{
|
||||
lastMember.Comment = lineComment;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Strips C++ comments from a line (both // and /* */ style).
|
||||
/// </summary>
|
||||
private static string StripComments(string line)
|
||||
{
|
||||
// Remove // style comments
|
||||
int slashSlash = line.IndexOf("//");
|
||||
if (slashSlash >= 0)
|
||||
line = line.Substring(0, slashSlash);
|
||||
|
||||
// Remove /* */ style comments (simple - doesn't handle nested)
|
||||
int blockStart = line.IndexOf("/*");
|
||||
while (blockStart >= 0)
|
||||
{
|
||||
int blockEnd = line.IndexOf("*/", blockStart + 2);
|
||||
if (blockEnd >= 0)
|
||||
line = line.Substring(0, blockStart) + line.Substring(blockEnd + 2);
|
||||
else
|
||||
line = line.Substring(0, blockStart);
|
||||
blockStart = line.IndexOf("/*");
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
private static int CountChar(string s, char c)
|
||||
{
|
||||
int count = 0;
|
||||
foreach (var ch in s)
|
||||
if (ch == c) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes a C++ value literal to a C# compatible one.
|
||||
/// </summary>
|
||||
private static string NormalizeCppValue(string value)
|
||||
{
|
||||
value = value.Trim().TrimEnd(',');
|
||||
|
||||
// Remove 'u' or 'U' suffix from integer literals
|
||||
if (value.EndsWith("u", StringComparison.OrdinalIgnoreCase) &&
|
||||
!value.EndsWith("0xu", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var candidate = value.Substring(0, value.Length - 1);
|
||||
if (IsIntegerLiteral(candidate))
|
||||
return candidate;
|
||||
}
|
||||
|
||||
// Normalize C++ float suffix to valid C# float literal
|
||||
if (value.EndsWith("f", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
value = value.Substring(0, value.Length - 1);
|
||||
if (value.EndsWith("."))
|
||||
value += "0";
|
||||
return value + "f";
|
||||
}
|
||||
|
||||
// If it's a float-looking literal without suffix, add f
|
||||
if (value.Contains(".") && !value.Contains("\""))
|
||||
return value + "f";
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static bool IsIntegerLiteral(string s)
|
||||
{
|
||||
s = s.Trim();
|
||||
if (s.Length == 0) return false;
|
||||
if (s.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
|
||||
return s.Length > 2 && s.Substring(2).All(c => "0123456789abcdefABCDEF".Contains(c));
|
||||
var start = s[0] == '-' ? 1 : 0;
|
||||
if (start >= s.Length) return false;
|
||||
return s.Substring(start).All(char.IsDigit);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
namespace Daybreak.Shared.Models.Api;
|
||||
public sealed record MainPlayerBuildContext(uint PrimaryProfessionId, uint UnlockedProfessions, uint[] UnlockedCharacterSkills, uint[] UnlockedAccountSkills)
|
||||
public sealed record MainPlayerBuildContext(uint PrimaryProfessionId, uint UnlockedProfessions, uint[] UnlockedCharacterSkills)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -7,6 +7,5 @@ public sealed class BuildComponentContext
|
||||
public required uint PrimaryProfessionId { get; init; }
|
||||
public required uint UnlockedProfessions { get; init; }
|
||||
public required uint[] CharacterUnlockedSkills { get; init; }
|
||||
public required uint[] AccountUnlockedSkills { get; init; }
|
||||
public required List<IBuildEntry> AvailableBuilds { get; init; }
|
||||
}
|
||||
|
||||
+1
-1
@@ -48,6 +48,6 @@
|
||||
<Platform Project="x64" />
|
||||
</Project>
|
||||
<Project Path="Daybreak.Generators/Daybreak.Generators.csproj">
|
||||
<Platform Project="x64" />
|
||||
<Platform Project="Any CPU" />
|
||||
</Project>
|
||||
</Solution>
|
||||
|
||||
+518
@@ -0,0 +1,518 @@
|
||||
#pragma once
|
||||
|
||||
namespace GW
|
||||
{
|
||||
namespace Constants
|
||||
{
|
||||
namespace ModelID
|
||||
{
|
||||
// this is actually agent->PlayerNumber for agents
|
||||
namespace Minipet
|
||||
{
|
||||
// First Year
|
||||
constexpr int Charr = 230; // Miniature Charr Shaman (purple)
|
||||
constexpr int Dragon = 231; // Miniature Bone Dragon (green)
|
||||
constexpr int Rurik = 232; // Miniature Prince Rurik (gold)
|
||||
constexpr int Shiro = 233; // Miniature Shiro (gold)
|
||||
constexpr int Titan = 234; // Miniature Burning Titan (purple)
|
||||
constexpr int Kirin = 235; // Miniature Kirin (purple)
|
||||
constexpr int NecridHorseman = 236; // Miniature Necrid Horseman (white)
|
||||
constexpr int JadeArmor = 237; // Miniature Jade Armor (white)
|
||||
constexpr int Hydra = 238; // Miniature Hydra (white)
|
||||
constexpr int FungalWallow = 239; // Miniature Fungal Wallow (white)
|
||||
constexpr int SiegeTurtle = 240; // Miniature Siege Turtle (white)
|
||||
constexpr int TempleGuardian = 241; // Miniature Temple Guardian (white)
|
||||
constexpr int JungleTroll = 242; // Miniature Jungle Troll (white)
|
||||
constexpr int WhiptailDevourer = 243; // Miniature Whiptail Devourer (white)
|
||||
// Second Year
|
||||
constexpr int Gwen = 244; // Miniature Gwen (green)
|
||||
constexpr int GwenDoll = 245; // Miniature Gwen Doll (??)
|
||||
constexpr int WaterDjinn = 246; // Miniature Water Djinn (gold)
|
||||
constexpr int Lich = 247; // Miniature Lich (gold)
|
||||
constexpr int Elf = 248; // Miniature Elf (purple)
|
||||
constexpr int PalawaJoko = 249; // Miniature Palawa Joko (purple)
|
||||
constexpr int Koss = 250; // Miniature Koss (purple)
|
||||
constexpr int MandragorImp = 251; // Miniature Mandragor Imp (white)
|
||||
constexpr int HeketWarrior = 252; // Miniature Heket Warrior (white)
|
||||
constexpr int HarpyRanger = 253; // Miniature Harpy Ranger (white)
|
||||
constexpr int Juggernaut = 254; // Miniature Juggernaut (white)
|
||||
constexpr int WindRider = 255; // Miniature Wind Rider (white)
|
||||
constexpr int FireImp = 256; // Miniature Fire Imp (white)
|
||||
constexpr int Aatxe = 257; // Miniature Aatxe (white)
|
||||
constexpr int ThornWolf = 258; // Miniature Thorn Wolf (white)
|
||||
// Third Year
|
||||
constexpr int Abyssal = 259; // Miniature Abyssal (white)
|
||||
constexpr int BlackBeast = 260; // Miniature Black Beast of Aaaaarrrrrrgghh (gold)
|
||||
constexpr int Freezie = 261; // Miniature Freezie (purple)
|
||||
constexpr int Irukandji = 262; // Miniature Irukandji (white)
|
||||
constexpr int MadKingThorn = 263; // Miniature Mad King Thorn (green)
|
||||
constexpr int ForestMinotaur = 264; // Miniature Forest Minotaur (white)
|
||||
constexpr int Mursaat = 265; // Miniature Mursaat (white)
|
||||
constexpr int Nornbear = 266; // Miniature Nornbear (purple)
|
||||
constexpr int Ooze = 267; // Miniature Ooze (purple)
|
||||
constexpr int Raptor = 268; // Miniature Raptor (white)
|
||||
constexpr int RoaringEther = 269; // Miniature Roaring Ether (white)
|
||||
constexpr int CloudtouchedSimian = 270; // Miniature Cloudtouched Simian (white)
|
||||
constexpr int CaveSpider = 271; // Miniature Cave Spider (white)
|
||||
constexpr int WhiteRabbit = 272; // White Rabbit (gold)
|
||||
// Fourth Year
|
||||
constexpr int WordofMadness = 273; // Miniature Word of Madness (white)
|
||||
constexpr int DredgeBrute = 274; // Miniature Dredge Brute (white)
|
||||
constexpr int TerrorwebDryder = 275; // Miniature Terrorweb Dryder (white)
|
||||
constexpr int Abomination = 276; // Miniature Abomination (white)
|
||||
constexpr int KraitNeoss = 277; // Miniature Krait Neoss (white)
|
||||
constexpr int DesertGriffon = 278; // Miniature Desert Griffon (white)
|
||||
constexpr int Kveldulf = 279; // Miniature Kveldulf (white)
|
||||
constexpr int QuetzalSly = 280; // Miniature Quetzal Sly (white)
|
||||
constexpr int Jora = 281; // Miniature Jora (purple)
|
||||
constexpr int FlowstoneElemental = 282; // Miniature Flowstone Elemental (purple)
|
||||
constexpr int Nian = 283; // Miniature Nian (purple)
|
||||
constexpr int DagnarStonepate = 284; // Miniature Dagnar Stonepate (gold)
|
||||
constexpr int FlameDjinn = 285; // Miniature Flame Djinn (gold)
|
||||
constexpr int EyeOfJanthir = 286; // Miniature Eye of Janthir (green)
|
||||
// Fifth Year
|
||||
constexpr int Seer = 287; // Miniature Seer (white)
|
||||
constexpr int SiegeDevourer = 288; // Miniature Siege Devourer (white)
|
||||
constexpr int ShardWolf = 289; // Miniature Shard Wolf (white)
|
||||
constexpr int FireDrake = 290; // Miniature Fire Drake (white)
|
||||
constexpr int SummitGiantHerder = 291; // Miniature Summit Giant Herder (white)
|
||||
constexpr int OphilNahualli = 292; // Miniature Ophil Nahualli (white)
|
||||
constexpr int CobaltScabara = 293; // Miniature Cobalt Scabara (white)
|
||||
constexpr int ScourgeManta = 294; // Miniature Scourge Manta (white)
|
||||
constexpr int Ventari = 295; // Miniature Ventari (purple)
|
||||
constexpr int Oola = 296; // Miniature Oola (purple)
|
||||
constexpr int CandysmithMarley = 297; // Miniature CandysmithMarley (purple)
|
||||
constexpr int ZhuHanuku = 298; // Miniature Zhu Hanuku (gold)
|
||||
constexpr int KingAdelbern = 299; // Miniature King Adelbern (gold)
|
||||
constexpr int MOX1 = 300; // Miniature M.O.X. (color?)
|
||||
constexpr int MOX2 = 301; // Miniature M.O.X. (color?)
|
||||
constexpr int MOX3 = 302; // Miniature M.O.X. (green)
|
||||
constexpr int MOX4 = 303; // Miniature M.O.X. (color?)
|
||||
constexpr int MOX5 = 304; // Miniature M.O.X. (color?)
|
||||
constexpr int MOX6 = 305; // Miniature M.O.X. (color?)
|
||||
|
||||
// In-game rewards and promotionals
|
||||
constexpr int BrownRabbit = 306; // Miniature Brown Rabbit
|
||||
constexpr int Yakkington = 307; // Miniature Yakkington
|
||||
// constexpr int Unknown308 = 308;
|
||||
constexpr int CollectorsEditionKuunavang = 309; // Miniature Kuunavang (green)
|
||||
constexpr int GrayGiant = 310;
|
||||
constexpr int Asura = 311;
|
||||
constexpr int DestroyerOfFlesh = 312;
|
||||
constexpr int PolarBear = 313;
|
||||
constexpr int CollectorsEditionVaresh = 314;
|
||||
constexpr int Mallyx = 315;
|
||||
constexpr int Ceratadon = 316;
|
||||
|
||||
// Misc.
|
||||
constexpr int Kanaxai = 317;
|
||||
constexpr int Panda = 318;
|
||||
constexpr int IslandGuardian = 319;
|
||||
constexpr int NagaRaincaller = 320;
|
||||
constexpr int LonghairYeti = 321;
|
||||
constexpr int Oni = 322;
|
||||
constexpr int ShirokenAssassin = 323;
|
||||
constexpr int Vizu = 324;
|
||||
constexpr int ZhedShadowhoof = 325;
|
||||
constexpr int Grawl = 326;
|
||||
constexpr int GhostlyHero = 327;
|
||||
|
||||
// Special events
|
||||
constexpr int Pig = 328;
|
||||
constexpr int GreasedLightning = 329;
|
||||
constexpr int WorldFamousRacingBeetle = 330;
|
||||
constexpr int CelestialPig = 331;
|
||||
constexpr int CelestialRat = 332;
|
||||
constexpr int CelestialOx = 333;
|
||||
constexpr int CelestialTiger = 334;
|
||||
constexpr int CelestialRabbit = 335;
|
||||
constexpr int CelestialDragon = 336;
|
||||
constexpr int CelestialSnake = 337;
|
||||
constexpr int CelestialHorse = 338;
|
||||
constexpr int CelestialSheep = 339;
|
||||
constexpr int CelestialMonkey = 340;
|
||||
constexpr int CelestialRooster = 341;
|
||||
constexpr int CelestialDog = 342;
|
||||
|
||||
// In-game
|
||||
constexpr int BlackMoaChick = 343;
|
||||
constexpr int Dhuum = 344;
|
||||
constexpr int MadKingsGuard = 345;
|
||||
constexpr int SmiteCrawler = 346;
|
||||
|
||||
// Zaishen strongboxes, and targetable minipets
|
||||
constexpr int GuildLord = 347;
|
||||
constexpr int HighPriestZhang = 348;
|
||||
constexpr int GhostlyPriest = 349;
|
||||
constexpr int RiftWarden = 350;
|
||||
}
|
||||
|
||||
namespace SummoningStone
|
||||
{
|
||||
constexpr int MercantileMerchant = 467;
|
||||
constexpr int ZaishenArcher = 468;
|
||||
constexpr int ZaishenAvatarOfBalthazar = 469;
|
||||
constexpr int ZaishenChampionOfBalthazar = 470;
|
||||
constexpr int ZaishenPriestOfBalthazar = 471;
|
||||
constexpr int ZaishenFootman = 472;
|
||||
constexpr int ZaishenGuildLord = 473;
|
||||
constexpr int MysteriousCrystalSpider = 490;
|
||||
constexpr int MysteriousSaltsprayDragon = 491;
|
||||
constexpr int MysteriousRestlessCorpse = 492;
|
||||
constexpr int MysteriousSmokePhantom = 493;
|
||||
constexpr int MysteriousSwarmOfBees = 494;
|
||||
constexpr int AutomatonGolem = 512;
|
||||
constexpr int IgneousFireImp = 513;
|
||||
constexpr int JadeiteSiegeTurtle = 514;
|
||||
constexpr int DemonicOni = 515;
|
||||
constexpr int AmberJuggernaut = 516;
|
||||
constexpr int MysticalGaki = 517;
|
||||
constexpr int GelatinousOoze = 518;
|
||||
constexpr int ChitinousDevourer = 519;
|
||||
constexpr int ArcticKveldulf = 520;
|
||||
constexpr int FossilizedRaptor = 521;
|
||||
constexpr int MischievousGrentch = 522;
|
||||
constexpr int FrostySnowman = 523;
|
||||
constexpr int GhastlyDreamRider = 524;
|
||||
}
|
||||
|
||||
// New bosses 2020-04-22
|
||||
enum
|
||||
{
|
||||
AbaddonsCursed = 1338,
|
||||
BladeAncientSyuShai = 1339,
|
||||
YoannhTheRebuilber = 1340,
|
||||
FureystSharpsight = 1341
|
||||
};
|
||||
|
||||
namespace FoW
|
||||
{
|
||||
constexpr int NimrosTheHunter = 1485;
|
||||
constexpr int MikoTheUnchained = 2015;
|
||||
}
|
||||
|
||||
namespace UW
|
||||
{
|
||||
constexpr int ChainedSoul = 2317;
|
||||
constexpr int DyingNightmare = 2318;
|
||||
constexpr int ObsidianBehemoth = 2319;
|
||||
constexpr int ObsidianGuardian = 2320;
|
||||
constexpr int TerrorwebDryder = 2321;
|
||||
constexpr int TerrorwebDryderSilver = 2322;
|
||||
constexpr int KeeperOfSouls = 2323;
|
||||
constexpr int TerrorwebQueen = 2324; // boss-like
|
||||
constexpr int SmiteCrawler = 2325;
|
||||
constexpr int WailingLord = 2326; // Note: same as FoW::Banshee
|
||||
constexpr int BanishedDreamRider = 2327;
|
||||
// 2324 ?
|
||||
constexpr int FourHorseman = 2329; // all four share the same id
|
||||
constexpr int MindbladeSpectre = 2330;
|
||||
|
||||
constexpr int DeadCollector = 2332;
|
||||
constexpr int DeadThresher = 2333;
|
||||
constexpr int ColdfireNight = 2334;
|
||||
constexpr int StalkingNight = 2335;
|
||||
// 2332 ?
|
||||
constexpr int ChargedBlackness = 2337;
|
||||
constexpr int GraspingDarkness = 2338;
|
||||
constexpr int BladedAatxe = 2339;
|
||||
|
||||
// 2336 ?
|
||||
constexpr int Slayer = 2391;
|
||||
constexpr int SkeletonOfDhuum1 = 2392;
|
||||
constexpr int SkeletonOfDhuum2 = 2393;
|
||||
constexpr int ChampionOfDhuum = 2394;
|
||||
constexpr int MinionOfDhuum = 2395;
|
||||
constexpr int Dhuum = 2396;
|
||||
|
||||
constexpr int Reapers = 2399; // outside dhuum chamber
|
||||
constexpr int ReapersAtDhuum = 2400; // in dhuum chamber
|
||||
constexpr int IceElemental = 2401; // friendly, during waste quest near dhuum.
|
||||
constexpr int KingFrozenwind = 2403;
|
||||
constexpr int TorturedSpirit1 = 2404; // friendly, during quest
|
||||
constexpr int Escort1 = 2407; // souls npc spawned by escort quest
|
||||
constexpr int Escort2 = 2408;
|
||||
constexpr int Escort3 = 2409;
|
||||
constexpr int Escort4 = 2410;
|
||||
constexpr int Escort5 = 2411;
|
||||
constexpr int Escort6 = 2412;
|
||||
constexpr int PitsSoul1 = 2413;
|
||||
constexpr int PitsSoul2 = 2414;
|
||||
constexpr int PitsSoul3 = 2415;
|
||||
constexpr int PitsSoul4 = 2416;
|
||||
|
||||
constexpr int TorturedSpirit = 2422;
|
||||
constexpr int MajorAlgheri = 2424;
|
||||
}
|
||||
|
||||
namespace FoW
|
||||
{
|
||||
constexpr int Banshee = 2377; // Note: same as UW::WailingLord
|
||||
|
||||
constexpr int MahgoHydra = 2847;
|
||||
constexpr int ArmoredCaveSpider = 2851;
|
||||
constexpr int SmokeWalker = 2852;
|
||||
constexpr int ObsidianFurnanceDrake = 2853;
|
||||
constexpr int DoubtersDryder = 2854;
|
||||
constexpr int ShadowMesmer = 2855;
|
||||
constexpr int ShadowElemental = 2856;
|
||||
constexpr int ShadowMonk = 2857;
|
||||
constexpr int ShadowWarrior = 2858;
|
||||
constexpr int ShadowRanger = 2859;
|
||||
constexpr int ShadowBeast = 2860;
|
||||
constexpr int Abyssal = 2861; // Note: same as ShadowOverlord.
|
||||
constexpr int ShadowOverlord = 2861; // Note: same as Abyssal.
|
||||
constexpr int SeedOfCorruption = 2862;
|
||||
constexpr int SpiritWood = 2863;
|
||||
constexpr int SpiritShepherd = 2864;
|
||||
constexpr int AncientSkale = 2865;
|
||||
constexpr int SnarlingDriftwood = 2866;
|
||||
constexpr int SkeletalEtherBreaker = 2867;
|
||||
constexpr int SkeletalIcehand = 2868;
|
||||
constexpr int SkeletalBond = 2869;
|
||||
constexpr int SkeletalBerserker = 2870;
|
||||
constexpr int SkeletalImpaler = 2871;
|
||||
constexpr int RockBorerWorm = 2872;
|
||||
constexpr int InfernalWurm = 2873;
|
||||
constexpr int DragonLich = 2874;
|
||||
constexpr int Menzies = 2875;
|
||||
// 2821 ?
|
||||
constexpr int Rastigan = 2877; // Friendly NPC
|
||||
constexpr int Griffons = 2878; // Friendly NPC
|
||||
constexpr int LordKhobay = 2879; // Unfriendly NPC
|
||||
constexpr int Forgemaster = 2880; // Friendly NPC
|
||||
// 2826 ?
|
||||
constexpr int TraitorousTempleGuard1 = 2882;
|
||||
constexpr int TraitorousTempleGuard2 = 2883;
|
||||
constexpr int TraitorousTempleGuard3 = 2884;
|
||||
// 2830 ?
|
||||
constexpr int ShardWolf = 2886;
|
||||
}
|
||||
|
||||
constexpr int Rotscale = 2888;
|
||||
|
||||
constexpr int Winnowing = 2926;
|
||||
constexpr int EoE = 2927;
|
||||
constexpr int FrozenSoil = 2933;
|
||||
constexpr int QZ = 2937;
|
||||
|
||||
namespace Urgoz
|
||||
{
|
||||
constexpr int HoppingVampire = 3796;
|
||||
constexpr int Urgoz = 3805;
|
||||
}
|
||||
|
||||
namespace Deep
|
||||
{
|
||||
constexpr int Kanaxai = 4110;
|
||||
constexpr int KanaxaiAspect = 4111;
|
||||
}
|
||||
|
||||
constexpr int Lacerate = 4283;
|
||||
constexpr int Equinox = 4287;
|
||||
constexpr int Famine = 4289;
|
||||
|
||||
namespace DoA
|
||||
{
|
||||
// Friendly
|
||||
constexpr int FoundrySnakes = 5272;
|
||||
|
||||
constexpr int BlackBeastOfArgh = 5201;
|
||||
constexpr int SmotheringTendril = 5265;
|
||||
constexpr int Fury = 5200;
|
||||
constexpr int LordJadoth = 5195;
|
||||
|
||||
// stygian lords
|
||||
constexpr int StygianLordNecro = 5196;
|
||||
constexpr int StygianLordMesmer = 5197;
|
||||
constexpr int StygianLordEle = 5198;
|
||||
constexpr int StygianLordMonk = 5199;
|
||||
constexpr int StygianLordDerv = 5214;
|
||||
constexpr int StygianLordRanger = 5215;
|
||||
|
||||
// margonites
|
||||
constexpr int MargoniteAnurKaya = 5217;
|
||||
constexpr int MargoniteAnurDabi = 5218;
|
||||
constexpr int MargoniteAnurSu = 5219;
|
||||
constexpr int MargoniteAnurKi = 5220;
|
||||
constexpr int MargoniteAnurVu = 5221;
|
||||
constexpr int MargoniteAnurTuk = 5222;
|
||||
constexpr int MargoniteAnurRuk = 5223;
|
||||
constexpr int MargoniteAnurRund = 5224;
|
||||
constexpr int MargoniteAnurMank = 5225;
|
||||
|
||||
// stygians
|
||||
constexpr int StygianHunger = 5226;
|
||||
constexpr int StygianBrute = 5227;
|
||||
constexpr int StygianGolem = 5228;
|
||||
constexpr int StygianHorror = 5229;
|
||||
constexpr int StygianFiend = 5230;
|
||||
|
||||
// tormentors in veil
|
||||
constexpr int VeilMindTormentor = 5231;
|
||||
constexpr int VeilSoulTormentor = 5232;
|
||||
constexpr int VeilWaterTormentor = 5233;
|
||||
constexpr int VeilHeartTormentor = 5234;
|
||||
constexpr int VeilFleshTormentor = 5235;
|
||||
constexpr int VeilSpiritTormentor = 5236;
|
||||
constexpr int VeilEarthTormentor = 5237;
|
||||
constexpr int VeilSanityTormentor = 5238;
|
||||
// tormentors
|
||||
constexpr int MindTormentor = 5255;
|
||||
constexpr int SoulTormentor = 5256;
|
||||
constexpr int WaterTormentor = 5257;
|
||||
constexpr int HeartTormentor = 5258;
|
||||
constexpr int FleshTormentor = 5259;
|
||||
constexpr int SpiritTormentor = 5260;
|
||||
constexpr int EarthTormentor = 5261;
|
||||
constexpr int SanityTormentor = 5263;
|
||||
|
||||
// titans
|
||||
constexpr int MiseryTitan = 5246;
|
||||
constexpr int RageTitan = 5247;
|
||||
constexpr int DementiaTitan = 5248;
|
||||
constexpr int AnguishTitan = 5249;
|
||||
constexpr int DespairTitan = 5250;
|
||||
constexpr int FuryTitan = 5251;
|
||||
constexpr int RageTitan2 = 5252;
|
||||
constexpr int DementiaTitan2 = 5253;
|
||||
constexpr int DespairTitan2 = 5254;
|
||||
|
||||
constexpr int TorturewebDryder = 5266;
|
||||
constexpr int GreaterDreamRider = 5267;
|
||||
constexpr int GreaterDreamRider2 = 5268;
|
||||
}
|
||||
|
||||
constexpr int ProphetVaresh = 5343;
|
||||
constexpr int CommanderVaresh = 5344;
|
||||
|
||||
// Spirits
|
||||
constexpr int InfuriatingHeat = 5766;
|
||||
constexpr int Quicksand = 5769;
|
||||
|
||||
namespace PolymockSummon
|
||||
{
|
||||
enum
|
||||
{
|
||||
// Polymocks
|
||||
MursaatElementalist = 5898,
|
||||
FlameDjinn = 5899,
|
||||
IceImp = 5900,
|
||||
NagaShaman = 5901
|
||||
};
|
||||
}
|
||||
|
||||
constexpr int EbonVanguardAssassin = 5903;
|
||||
|
||||
namespace EotnDungeons
|
||||
{
|
||||
constexpr int DiscOfChaos = 6122;
|
||||
constexpr int PlagueOfDestruction = 6134;
|
||||
constexpr int ZhimMonns = 6297;
|
||||
constexpr int Khabuus = 6299;
|
||||
constexpr int DuncanTheBlack = 6456;
|
||||
constexpr int JusticiarThommis = 6457;
|
||||
constexpr int RandStormweaver = 6458;
|
||||
constexpr int Selvetarm = 6459;
|
||||
constexpr int Forgewright = 6460;
|
||||
constexpr int HavokSoulwail = 6478;
|
||||
constexpr int RragarManeater3 = 6609; // lvl 3
|
||||
constexpr int RragarManeater12 = 6610; // lvl 1 and 2
|
||||
constexpr int Arachni = 6844;
|
||||
constexpr int Hidesplitter = 6852;
|
||||
constexpr int PrismaticOoze = 6857;
|
||||
constexpr int IlsundurLordofFire = 6865;
|
||||
constexpr int EldritchEttin = 6872;
|
||||
constexpr int TPSRegulartorGolem = 6883;
|
||||
constexpr int MalfunctioningEnduringGolem = 6885;
|
||||
constexpr int StormcloudIncubus = 6902;
|
||||
constexpr int CyndrTheMountainHeart = 6965;
|
||||
constexpr int InfernalSiegeWurm = 6978; // kath lvl1 boss
|
||||
constexpr int Frostmaw = 6983;
|
||||
constexpr int RemnantOfAntiquities = 6985;
|
||||
constexpr int MurakaiLadyOfTheNight = 7059;
|
||||
constexpr int ZoldarkTheUnholy = 7061;
|
||||
|
||||
constexpr int Brigand = 7060; // soo
|
||||
constexpr int FendiNin = 7064;
|
||||
constexpr int SoulOfFendiNin = 7065;
|
||||
|
||||
constexpr int KeymasterOfMurakai = 7069;
|
||||
}
|
||||
|
||||
namespace BonusMissionPack
|
||||
{
|
||||
constexpr int WarAshenskull = 7130;
|
||||
constexpr int RoxAshreign = 7131;
|
||||
constexpr int AnrakTindershot = 7132;
|
||||
constexpr int DettMortash = 7133;
|
||||
constexpr int AkinCinderspire = 7134;
|
||||
constexpr int TwangSootpaws = 7135;
|
||||
constexpr int MagisEmberglow = 7136;
|
||||
constexpr int MerciaTheSmug = 7165;
|
||||
constexpr int OptimusCaliph = 7166;
|
||||
constexpr int LazarusTheDire = 7167;
|
||||
constexpr int AdmiralJakman = 7230;
|
||||
constexpr int PalawaJoko = 7249;
|
||||
constexpr int YuriTheHand = 7197;
|
||||
constexpr int MasterRiyo = 7198;
|
||||
constexpr int CaptainSunpu = 7200;
|
||||
constexpr int MinisterWona = 7201;
|
||||
}
|
||||
|
||||
namespace EotnDungeons
|
||||
{
|
||||
constexpr int AngrySnowman = 7462;
|
||||
}
|
||||
|
||||
constexpr int Boo = 7500;
|
||||
|
||||
/* Birthday Minis */
|
||||
/* unknowns are commented as a guess as inventory name but fit a pattern of id schema */
|
||||
namespace Minipet
|
||||
{
|
||||
// More in-game drops and rewards
|
||||
constexpr int MiniatureLegionnaire = 8035;
|
||||
}
|
||||
|
||||
constexpr int LockedChest = 8192; // this is actually ->ExtraType
|
||||
|
||||
namespace Minipet
|
||||
{
|
||||
constexpr int MiniatureConfessorDorian = 8344;
|
||||
constexpr int MiniaturePrincessSalma = 8349;
|
||||
constexpr int MiniatureLivia = 8350;
|
||||
constexpr int MiniatureEvennia = 8351;
|
||||
constexpr int MiniatureConfessorIsaiah = 8352;
|
||||
// missing miniature 8298 ?
|
||||
constexpr int MiniaturePeacekeeperEnforcer = 8354;
|
||||
constexpr int MiniatureMinisterReiko = 9038;
|
||||
constexpr int MiniatureEcclesiateXunRao = 9039;
|
||||
}
|
||||
|
||||
namespace SummoningStone
|
||||
{
|
||||
constexpr int ImperialCripplingSlash = 9043;
|
||||
constexpr int ImperialTripleChop = 9044;
|
||||
constexpr int ImperialBarrage = 9045;
|
||||
constexpr int ImperialQuiveringBlade = 9046;
|
||||
constexpr int TenguHundredBlades = 9047;
|
||||
constexpr int TenguBroadHeadArrow = 9048;
|
||||
constexpr int TenguPalmStrike = 9049;
|
||||
constexpr int TenguLifeSheath = 9050;
|
||||
constexpr int TenguAngchuElementalist = 9051;
|
||||
constexpr int TenguFeveredDreams = 9052;
|
||||
constexpr int TenguSpitefulSpirit = 9053;
|
||||
constexpr int TenguPreservation = 9054;
|
||||
constexpr int TenguPrimalRage = 9055;
|
||||
constexpr int TenguGlassArrows = 9056;
|
||||
constexpr int TenguWayOftheAssassin = 9057;
|
||||
constexpr int TenguPeaceandHarmony = 9058;
|
||||
constexpr int TenguSandstorm = 9059;
|
||||
constexpr int TenguPanic = 9060;
|
||||
constexpr int TenguAuraOftheLich = 9061;
|
||||
constexpr int TenguDefiantWasXinrae = 9062;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,361 @@
|
||||
// ReSharper disable CppUnusedIncludeDirective
|
||||
#pragma once
|
||||
|
||||
#include "AgentIDs.h"
|
||||
#include "ItemIDs.h"
|
||||
#include "Maps.h"
|
||||
#include "QuestIDs.h"
|
||||
#include "Skills.h"
|
||||
|
||||
namespace GW {
|
||||
namespace Constants {
|
||||
|
||||
enum class Campaign : uint32_t { Core, Prophecies, Factions, Nightfall, EyeOfTheNorth, BonusMissionPack };
|
||||
enum class Difficulty { Normal, Hard };
|
||||
enum class InstanceType { Outpost, Explorable, Loading };
|
||||
|
||||
enum class Profession : uint32_t {
|
||||
None, Warrior, Ranger, Monk, Necromancer, Mesmer,
|
||||
Elementalist, Assassin, Ritualist, Paragon, Dervish
|
||||
};
|
||||
enum class ProfessionByte : uint8_t {
|
||||
None, Warrior, Ranger, Monk, Necromancer, Mesmer,
|
||||
Elementalist, Assassin, Ritualist, Paragon, Dervish
|
||||
};
|
||||
static const char* GetProfessionAcronym(Profession prof) {
|
||||
switch (prof) {
|
||||
case GW::Constants::Profession::None: return "X";
|
||||
case GW::Constants::Profession::Warrior: return "W";
|
||||
case GW::Constants::Profession::Ranger: return "R";
|
||||
case GW::Constants::Profession::Monk: return "Mo";
|
||||
case GW::Constants::Profession::Necromancer: return "N";
|
||||
case GW::Constants::Profession::Mesmer: return "Me";
|
||||
case GW::Constants::Profession::Elementalist: return "E";
|
||||
case GW::Constants::Profession::Assassin: return "A";
|
||||
case GW::Constants::Profession::Ritualist: return "Rt";
|
||||
case GW::Constants::Profession::Paragon: return "P";
|
||||
case GW::Constants::Profession::Dervish: return "D";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
static const wchar_t* GetWProfessionAcronym(Profession prof) {
|
||||
switch (prof) {
|
||||
case GW::Constants::Profession::None: return L"X";
|
||||
case GW::Constants::Profession::Warrior: return L"W";
|
||||
case GW::Constants::Profession::Ranger: return L"R";
|
||||
case GW::Constants::Profession::Monk: return L"Mo";
|
||||
case GW::Constants::Profession::Necromancer: return L"N";
|
||||
case GW::Constants::Profession::Mesmer: return L"Me";
|
||||
case GW::Constants::Profession::Elementalist: return L"E";
|
||||
case GW::Constants::Profession::Assassin: return L"A";
|
||||
case GW::Constants::Profession::Ritualist: return L"Rt";
|
||||
case GW::Constants::Profession::Paragon: return L"P";
|
||||
case GW::Constants::Profession::Dervish: return L"D";
|
||||
default: return L"";
|
||||
}
|
||||
}
|
||||
|
||||
namespace Preference {
|
||||
enum class CharSortOrder : uint32_t {
|
||||
None, Alphabetize, PvPRP
|
||||
};
|
||||
}
|
||||
|
||||
enum class Attribute : uint32_t {
|
||||
FastCasting, IllusionMagic, DominationMagic, InspirationMagic, // mesmer
|
||||
BloodMagic, DeathMagic, SoulReaping, Curses, // necro
|
||||
AirMagic, EarthMagic, FireMagic, WaterMagic, EnergyStorage, // ele
|
||||
HealingPrayers, SmitingPrayers, ProtectionPrayers, DivineFavor, // monk
|
||||
Strength, AxeMastery, HammerMastery, Swordsmanship, Tactics, // warrior
|
||||
BeastMastery, Expertise, WildernessSurvival, Marksmanship, // ranger
|
||||
DaggerMastery = 29, DeadlyArts, ShadowArts, // assassin (most)
|
||||
Communing, RestorationMagic, ChannelingMagic, // ritualist (most)
|
||||
CriticalStrikes, SpawningPower, // sin/rit primary (gw is weird)
|
||||
SpearMastery, Command, Motivation, Leadership, // paragon
|
||||
ScytheMastery, WindPrayers, EarthPrayers, Mysticism, // derv
|
||||
None = 0xff
|
||||
};
|
||||
enum class AttributeByte : uint8_t {
|
||||
FastCasting, IllusionMagic, DominationMagic, InspirationMagic, // mesmer
|
||||
BloodMagic, DeathMagic, SoulReaping, Curses, // necro
|
||||
AirMagic, EarthMagic, FireMagic, WaterMagic, EnergyStorage, // ele
|
||||
HealingPrayers, SmitingPrayers, ProtectionPrayers, DivineFavor, // monk
|
||||
Strength, AxeMastery, HammerMastery, Swordsmanship, Tactics, // warrior
|
||||
BeastMastery, Expertise, WildernessSurvival, Marksmanship, // ranger
|
||||
DaggerMastery = 29, DeadlyArts, ShadowArts, // assassin (most)
|
||||
Communing, RestorationMagic, ChannelingMagic, // ritualist (most)
|
||||
CriticalStrikes, SpawningPower, // sin/rit primary (gw is weird)
|
||||
SpearMastery, Command, Motivation, Leadership, // paragon
|
||||
ScytheMastery, WindPrayers, EarthPrayers, Mysticism, // derv
|
||||
None = 0xff
|
||||
};
|
||||
|
||||
enum class Bag : uint8_t {
|
||||
None, Backpack, Belt_Pouch, Bag_1, Bag_2, Equipment_Pack,
|
||||
Material_Storage, Unclaimed_Items, Storage_1, Storage_2,
|
||||
Storage_3, Storage_4, Storage_5, Storage_6, Storage_7,
|
||||
Storage_8, Storage_9, Storage_10, Storage_11, Storage_12,
|
||||
Storage_13, Storage_14, Equipped_Items, Max
|
||||
};
|
||||
inline Bag& operator++(Bag& bag) {
|
||||
if (bag == Bag::Max) return bag;
|
||||
bag = static_cast<Bag>(static_cast<uint8_t>(bag) + 1);
|
||||
return bag;
|
||||
}
|
||||
inline Bag operator++(Bag& bag, int) {
|
||||
const Bag cpy = bag;
|
||||
++bag;
|
||||
return cpy;
|
||||
}
|
||||
|
||||
// Order of storage panes.
|
||||
enum class StoragePane : uint8_t {
|
||||
Storage_1,Storage_2,Storage_3,Storage_4,Storage_5,
|
||||
Storage_6,Storage_7,Storage_8,Storage_9,Storage_10,
|
||||
Storage_11,Storage_12,Storage_13,Storage_14,Material_Storage
|
||||
};
|
||||
|
||||
constexpr size_t BagMax = (size_t)Bag::Max;
|
||||
|
||||
enum class AgentType {
|
||||
Living = 0xDB, Gadget = 0x200, Item = 0x400
|
||||
};
|
||||
|
||||
enum class Allegiance : uint8_t {
|
||||
Ally_NonAttackable = 0x1, Neutral = 0x2, Enemy = 0x3, Spirit_Pet = 0x4, Minion = 0x5, Npc_Minipet = 0x6
|
||||
};
|
||||
|
||||
enum class ItemType : uint8_t {
|
||||
Salvage, Axe = 2, Bag, Boots, Bow, Bundle, Chestpiece, Rune_Mod, Usable, Dye,
|
||||
Materials_Zcoins, Offhand, Gloves, Hammer = 15, Headpiece, CC_Shards,
|
||||
Key, Leggings, Gold_Coin, Quest_Item, Wand, Shield = 24, Staff = 26, Sword,
|
||||
Kit = 29, Trophy, Scroll, Daggers, Present, Minipet, Scythe, Spear, Storybook = 43, Costume, Costume_Headpiece, Unknown = 0xff
|
||||
};
|
||||
|
||||
enum HeroID : uint32_t {
|
||||
NoHero, Norgu, Goren, Tahlkora, MasterOfWhispers, AcolyteJin, Koss,
|
||||
Dunkoro, AcolyteSousuke, Melonni, ZhedShadowhoof, GeneralMorgahn,
|
||||
MargridTheSly, Zenmai, Olias, Razah, MOX, KeiranThackeray, Jora,
|
||||
PyreFierceshot, Anton, Livia, Hayda, Kahmu, Gwen, Xandra, Vekk,
|
||||
Ogden, Merc1, Merc2, Merc3, Merc4, Merc5, Merc6, Merc7, Merc8,
|
||||
Miku, ZeiRi, Devona, GhostofAlthea, Count
|
||||
};
|
||||
|
||||
enum class MaterialSlot : uint32_t {
|
||||
Bone, IronIngot, TannedHideSquare, Scale, ChitinFragment,
|
||||
BoltofCloth, WoodPlank, GraniteSlab = 8,
|
||||
PileofGlitteringDust, PlantFiber, Feather,
|
||||
|
||||
FurSquare, BoltofLinen, BoltofDamask, BoltofSilk,
|
||||
GlobofEctoplasm, SteelIngot, DeldrimorSteelIngot,
|
||||
MonstrousClaw, MonstrousEye, MonstrousFang, Ruby,
|
||||
Sapphire, Diamond, OnyxGemstone, LumpofCharcoal,
|
||||
ObsidianShard, TemperedGlassVial = 29, LeatherSquare,
|
||||
ElonianLeatherSquare, VialofInk, RollofParchment,
|
||||
RollofVellum, SpiritwoodPlank, AmberChunk, JadeiteShard,
|
||||
|
||||
BronzeZCoin, SilverZCoin, GoldZCoin,
|
||||
|
||||
Count
|
||||
};
|
||||
|
||||
constexpr std::array HeroProfs = {
|
||||
Profession::None,
|
||||
Profession::Mesmer, // Norgu
|
||||
Profession::Warrior,// Goren
|
||||
Profession::Monk, // Tahlkora
|
||||
Profession::Necromancer, // Master Of Whispers
|
||||
Profession::Ranger, // Acolyte Jin
|
||||
Profession::Warrior, // Koss
|
||||
Profession::Monk, // Dunkoro
|
||||
Profession::Elementalist, // Acolyte Sousuke
|
||||
Profession::Dervish, // Melonni
|
||||
Profession::Elementalist, // Zhed Shadowhoof
|
||||
Profession::Paragon, // General Morgahn
|
||||
Profession::Ranger, // Magrid The Sly
|
||||
Profession::Assassin, // Zenmai
|
||||
Profession::Necromancer, // Olias
|
||||
Profession::None, // Razah
|
||||
Profession::Dervish, // MOX
|
||||
Profession::Paragon, // Keiran Thackeray
|
||||
Profession::Warrior, // Jora
|
||||
Profession::Ranger, // Pyre Fierceshot
|
||||
Profession::Assassin, // Anton
|
||||
Profession::Necromancer, // Livia
|
||||
Profession::Paragon, // Hayda
|
||||
Profession::Dervish, // Kahmu
|
||||
Profession::Mesmer, // Gwen
|
||||
Profession::Ritualist, // Xandra
|
||||
Profession::Elementalist, // Vekk
|
||||
Profession::Monk, // Ogden
|
||||
Profession::None, // Mercenary Hero 1
|
||||
Profession::None, // Mercenary Hero 2
|
||||
Profession::None, // Mercenary Hero 3
|
||||
Profession::None, // Mercenary Hero 4
|
||||
Profession::None, // Mercenary Hero 5
|
||||
Profession::None, // Mercenary Hero 6
|
||||
Profession::None, // Mercenary Hero 7
|
||||
Profession::None, // Mercenary Hero 8
|
||||
Profession::Assassin, // Miku
|
||||
Profession::Ritualist, // Zei Ri
|
||||
Profession::Warrior, // Devona
|
||||
Profession::Mesmer // Ghost of Althea
|
||||
};
|
||||
|
||||
enum class TitleID : uint32_t {
|
||||
Hero, TyrianCarto, CanthanCarto, Gladiator, Champion, Kurzick,
|
||||
Luxon, Drunkard,
|
||||
Deprecated_SkillHunter, // Pre hard mode update version
|
||||
Survivor, KoaBD,
|
||||
Deprecated_TreasureHunter, // Old title, non-account bound
|
||||
Deprecated_Wisdom, // Old title, non-account bound
|
||||
ProtectorTyria,
|
||||
ProtectorCantha, Lucky, Unlucky, Sunspear, ElonianCarto,
|
||||
ProtectorElona, Lightbringer, LDoA, Commander, Gamer,
|
||||
SkillHunterTyria, VanquisherTyria, SkillHunterCantha,
|
||||
VanquisherCantha, SkillHunterElona, VanquisherElona,
|
||||
LegendaryCarto, LegendaryGuardian, LegendarySkillHunter,
|
||||
LegendaryVanquisher, Sweets, GuardianTyria, GuardianCantha,
|
||||
GuardianElona, Asuran, Deldrimor, Vanguard, Norn, MasterOfTheNorth,
|
||||
Party, Zaishen, TreasureHunter, Wisdom, Codex,
|
||||
None = 0xff
|
||||
};
|
||||
|
||||
enum class Tick { NOT_READY, READY };
|
||||
|
||||
enum class InterfaceSize { SMALL = -1, NORMAL, LARGE, LARGER };
|
||||
namespace HealthbarHeight {
|
||||
constexpr size_t Small = 24;
|
||||
constexpr size_t Normal = 22;
|
||||
constexpr size_t Large = 26;
|
||||
constexpr size_t Larger = 30;
|
||||
}
|
||||
|
||||
// travel, region, districts
|
||||
enum class ServerRegion {
|
||||
International = -2,
|
||||
America = 0,
|
||||
Korea,
|
||||
Europe,
|
||||
China,
|
||||
Japan,
|
||||
Unknown = 0xff
|
||||
};
|
||||
|
||||
// in-game language for maps and in-game text
|
||||
enum class Language {
|
||||
English,
|
||||
Korean,
|
||||
French,
|
||||
German,
|
||||
Italian,
|
||||
Spanish,
|
||||
TraditionalChinese,
|
||||
Japanese = 8,
|
||||
Polish,
|
||||
Russian,
|
||||
BorkBorkBork = 17,
|
||||
Unknown = 0xff
|
||||
};
|
||||
|
||||
enum class District { // arbitrary enum for game district
|
||||
Current,
|
||||
International,
|
||||
American,
|
||||
EuropeEnglish,
|
||||
EuropeFrench,
|
||||
EuropeGerman,
|
||||
EuropeItalian,
|
||||
EuropeSpanish,
|
||||
EuropePolish,
|
||||
EuropeRussian,
|
||||
AsiaKorean,
|
||||
AsiaChinese,
|
||||
AsiaJapanese,
|
||||
Unknown = 0xff
|
||||
};
|
||||
|
||||
namespace Range {
|
||||
constexpr float Touch = 144.f;
|
||||
constexpr float Adjacent = 166.0f;
|
||||
constexpr float Nearby = 252.0f;
|
||||
constexpr float Area = 322.0f;
|
||||
constexpr float Earshot = 1012.0f;
|
||||
constexpr float Spellcast = 1248.0f;
|
||||
constexpr float Spirit = 2512.0f;
|
||||
constexpr float SpiritExtended = 3500.0f;
|
||||
constexpr float Compass = 5000.0f;
|
||||
};
|
||||
|
||||
namespace SqrRange {
|
||||
constexpr float Adjacent = Range::Adjacent * Range::Adjacent;
|
||||
constexpr float Nearby = Range::Nearby * Range::Nearby;
|
||||
constexpr float Area = Range::Area * Range::Area;
|
||||
constexpr float Earshot = Range::Earshot * Range::Earshot;
|
||||
constexpr float Spellcast = Range::Spellcast * Range::Spellcast;
|
||||
constexpr float Spirit = Range::Spirit * Range::Spirit;
|
||||
constexpr float Compass = Range::Compass * Range::Compass;
|
||||
};
|
||||
|
||||
namespace DialogID {
|
||||
constexpr int UwTeleEnquire = 127; // "where can you teleport us to"
|
||||
constexpr int UwTelePlanes = 139;
|
||||
constexpr int UwTeleWastes = 140;
|
||||
constexpr int UwTeleLab = 141;
|
||||
constexpr int UwTeleMnt = 142;
|
||||
constexpr int UwTelePits = 143;
|
||||
constexpr int UwTelePools = 144;
|
||||
constexpr int UwTeleVale = 145;
|
||||
|
||||
constexpr int FowCraftArmor = 127;
|
||||
|
||||
constexpr int FerryKamadanToDocks = 133; // Assistant Hahnna
|
||||
constexpr int FerryDocksToKaineng = 136; // Mhenlo
|
||||
constexpr int FerryDocksToLA = 137; // Mhenlo
|
||||
constexpr int FerryGateToLA = 133; // Lionguard Neiro
|
||||
|
||||
// Profession Changer Dialogs.
|
||||
constexpr int ProfChangeWarrior = 0x184;
|
||||
constexpr int ProfChangeRanger = 0x284;
|
||||
constexpr int ProfChangeMonk = 0x384;
|
||||
constexpr int ProfChangeNecro = 0x484;
|
||||
constexpr int ProfChangeMesmer = 0x584;
|
||||
constexpr int ProfChangeEle = 0x684;
|
||||
constexpr int ProfChangeAssassin = 0x784;
|
||||
constexpr int ProfChangeRitualist = 0x884;
|
||||
constexpr int ProfChangeParagon = 0x984;
|
||||
constexpr int ProfChangeDervish = 0xA84;
|
||||
|
||||
constexpr int FactionMissionOutpost = 0x80000B;
|
||||
constexpr int NightfallMissionOutpost = 0x85;
|
||||
}
|
||||
|
||||
enum class EffectID : uint32_t {
|
||||
black_cloud = 1,
|
||||
mesmer_symbol = 4,
|
||||
green_cloud = 7,
|
||||
green_sparks = 8,
|
||||
necro_symbol = 9,
|
||||
ele_symbol = 11,
|
||||
white_clouds = 13,
|
||||
monk_symbol = 18,
|
||||
bleeding = 23,
|
||||
blind = 24,
|
||||
burning = 25,
|
||||
disease = 26,
|
||||
poison = 27,
|
||||
dazed = 28,
|
||||
weakness = 29, //cracked_armor has same EffectID
|
||||
assasin_symbol = 34,
|
||||
ritualist_symbol = 35,
|
||||
dervish_symbol = 36,
|
||||
};
|
||||
|
||||
namespace Camera {
|
||||
constexpr float FIRST_PERSON_DIST = 2.f;
|
||||
constexpr float DEFAULT_DIST = 750.f;
|
||||
}
|
||||
|
||||
constexpr size_t SkillMax = 0xd69;
|
||||
}
|
||||
}
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
#pragma once
|
||||
|
||||
namespace GW {
|
||||
namespace Constants {
|
||||
namespace ItemID { // aka item modelIDs
|
||||
constexpr int Dye = 146;
|
||||
|
||||
// items that make agents
|
||||
constexpr int GhostInTheBox = 6368;
|
||||
constexpr int GhastlyStone = 32557;
|
||||
constexpr int LegionnaireStone = 37810;
|
||||
|
||||
// materials
|
||||
constexpr int Bone = 921;
|
||||
constexpr int BoltofCloth = 925;
|
||||
constexpr int PileofGlitteringDust = 929;
|
||||
constexpr int Feather = 933;
|
||||
constexpr int PlantFiber = 934;
|
||||
constexpr int TannedHideSquare = 940;
|
||||
constexpr int WoodPlank = 946;
|
||||
constexpr int IronIngot = 948;
|
||||
constexpr int Scale = 953;
|
||||
constexpr int ChitinFragment = 954;
|
||||
constexpr int GraniteSlab = 955;
|
||||
|
||||
constexpr int AmberChunk = 6532;
|
||||
constexpr int BoltofDamask = 927;
|
||||
constexpr int BoltofLinen = 926;
|
||||
constexpr int BoltofSilk = 928;
|
||||
constexpr int DeldrimorSteelIngot = 950;
|
||||
constexpr int Diamond = 935;
|
||||
constexpr int ElonianLeatherSquare = 943;
|
||||
constexpr int FurSquare = 941;
|
||||
constexpr int GlobofEctoplasm = 930;
|
||||
constexpr int JadeiteShard = 6533;
|
||||
constexpr int LeatherSquare = 942;
|
||||
constexpr int LumpofCharcoal = 922;
|
||||
constexpr int MonstrousClaw = 923;
|
||||
constexpr int MonstrousEye = 931;
|
||||
constexpr int MonstrousFang = 932;
|
||||
constexpr int ObsidianShard = 945;
|
||||
constexpr int OnyxGemstone = 936;
|
||||
constexpr int RollofParchment = 951;
|
||||
constexpr int RollofVellum = 952;
|
||||
constexpr int Ruby = 937;
|
||||
constexpr int Sapphire = 938;
|
||||
constexpr int SpiritwoodPlank = 956;
|
||||
constexpr int SteelIngot = 949;
|
||||
constexpr int TemperedGlassVial = 939;
|
||||
constexpr int VialofInk = 944;
|
||||
|
||||
// XP scrolls
|
||||
constexpr int ScrollOfAdventurersInsight = 5853;
|
||||
constexpr int ScrollOfBerserkersInsight = 5595;
|
||||
constexpr int ScrollOfHerosInsight = 5594;
|
||||
constexpr int ScrollOfHuntersInsight = 5976;
|
||||
constexpr int ScrollOfRampagersInsight = 5975;
|
||||
constexpr int ScrollOfSlayersInsight = 5611;
|
||||
constexpr int ScrollOfTheLightbringer = 21233;
|
||||
|
||||
// pcons
|
||||
constexpr int SkalefinSoup = 17061;
|
||||
constexpr int PahnaiSalad = 17062;
|
||||
constexpr int MandragorRootCake = 19170;
|
||||
constexpr int Pies = 28436;
|
||||
constexpr int Cupcakes = 22269;
|
||||
constexpr int Apples = 28431;
|
||||
constexpr int Corns = 28432;
|
||||
constexpr int Eggs = 22752;
|
||||
constexpr int Kabobs = 17060;
|
||||
constexpr int Warsupplies = 35121;
|
||||
constexpr int LunarPig = 29424;
|
||||
constexpr int LunarRat = 29425;
|
||||
constexpr int LunarOx = 29426;
|
||||
constexpr int LunarTiger = 29427;
|
||||
constexpr int LunarRabbit = 29428;
|
||||
constexpr int LunarDragon = 29429;
|
||||
constexpr int LunarSnake = 29430;
|
||||
constexpr int LunarHorse = 29431;
|
||||
constexpr int LunarSheep = 29432;
|
||||
constexpr int LunarMonkey = 29433;
|
||||
constexpr int LunarRooster = 29434;
|
||||
constexpr int LunarDog = 29435;
|
||||
constexpr int ConsEssence = 24859;
|
||||
constexpr int ConsArmor = 24860;
|
||||
constexpr int ConsGrail = 24861;
|
||||
constexpr int ResScrolls = 26501;
|
||||
constexpr int Mobstopper = 32558;
|
||||
constexpr int Powerstone = 24862;
|
||||
|
||||
constexpr int Fruitcake = 21492;
|
||||
constexpr int RedBeanCake = 15479;
|
||||
constexpr int CremeBrulee = 15528;
|
||||
constexpr int SugaryBlueDrink = 21812;
|
||||
constexpr int ChocolateBunny = 22644;
|
||||
constexpr int JarOfHoney = 31150;
|
||||
constexpr int BRC = 31151;
|
||||
constexpr int GRC = 31152;
|
||||
constexpr int RRC = 31153;
|
||||
constexpr int KrytalLokum = 35125;
|
||||
constexpr int MinistreatOfPurity = 30208;
|
||||
|
||||
// level-1 alcohol
|
||||
constexpr int Eggnog = 6375;
|
||||
constexpr int DwarvenAle = 5585;
|
||||
constexpr int HuntersAle = 910;
|
||||
constexpr int Absinthe = 6367;
|
||||
constexpr int WitchsBrew = 6049;
|
||||
constexpr int Ricewine = 15477;
|
||||
constexpr int ShamrockAle = 22190;
|
||||
constexpr int Cider = 28435;
|
||||
|
||||
// level-5 alcohol
|
||||
constexpr int Grog = 30855;
|
||||
constexpr int SpikedEggnog = 6366;
|
||||
constexpr int AgedDwarvenAle = 24593;
|
||||
constexpr int AgedHuntersAle = 31145;
|
||||
constexpr int Keg = 31146;
|
||||
constexpr int FlaskOfFirewater = 2513;
|
||||
constexpr int KrytanBrandy = 35124;
|
||||
|
||||
// DoA Gemstones
|
||||
constexpr int MargoniteGem = 21128;
|
||||
constexpr int StygianGem = 21129;
|
||||
constexpr int TitanGem = 21130;
|
||||
constexpr int TormentGem = 21131;
|
||||
|
||||
// Holiday Drops
|
||||
constexpr int LunarToken = 21833;
|
||||
|
||||
constexpr int Lockpick = 22751;
|
||||
|
||||
constexpr int IdentificationKit = 2989;
|
||||
constexpr int IdentificationKit_Superior = 5899;
|
||||
constexpr int SalvageKit = 2992;
|
||||
constexpr int SalvageKit_Expert = 2991;
|
||||
constexpr int SalvageKit_Superior = 5900;
|
||||
|
||||
// Alcohol
|
||||
constexpr int BattleIsleIcedTea = 36682;
|
||||
constexpr int BottleOfJuniberryGin = 19172;
|
||||
constexpr int BottleOfVabbianWine = 19173;
|
||||
constexpr int ZehtukasJug = 19171;
|
||||
|
||||
// DP
|
||||
constexpr int FourLeafClover = 22191; // party-wide
|
||||
constexpr int OathOfPurity = 30206; // party-wide
|
||||
constexpr int PeppermintCandyCane = 6370;
|
||||
constexpr int RefinedJelly = 19039;
|
||||
constexpr int ShiningBladeRations = 35127;
|
||||
constexpr int WintergreenCandyCane = 21488;
|
||||
|
||||
// Morale
|
||||
constexpr int ElixirOfValor = 21227; // party-wide
|
||||
constexpr int Honeycomb = 26784; // party-wide
|
||||
constexpr int PumpkinCookie = 28433;
|
||||
constexpr int RainbowCandyCane = 21489; // party-wide
|
||||
constexpr int SealOfTheDragonEmpire = 30211; // party-wide
|
||||
|
||||
// Summons
|
||||
constexpr int GakiSummon = 30960;
|
||||
constexpr int TurtleSummon = 30966;
|
||||
|
||||
// Summons x3
|
||||
constexpr int TenguSummon = 30209;
|
||||
constexpr int ImperialGuardSummon = 30210;
|
||||
constexpr int WarhornSummon = 35126;
|
||||
|
||||
// Tonics
|
||||
constexpr int ELGwen = 36442;
|
||||
constexpr int ELMiku = 36451;
|
||||
constexpr int ELMargo = 36456;
|
||||
constexpr int ELZenmai = 36493;
|
||||
|
||||
// Other Consumables
|
||||
constexpr int ArmbraceOfTruth = 21127;
|
||||
constexpr int PhantomKey = 5882;
|
||||
constexpr int ResScroll = 26501;
|
||||
|
||||
// Weapons
|
||||
constexpr int DSR = 32823;
|
||||
constexpr int EternalBlade = 1045;
|
||||
constexpr int ObsidianEdge = 1900;
|
||||
constexpr int VoltaicSpear = 2071;
|
||||
constexpr int CrystallineSword = 399;
|
||||
|
||||
// Minis
|
||||
constexpr int MiniDhuum = 32822;
|
||||
|
||||
// Bundles
|
||||
constexpr int UnholyText = 2619;
|
||||
constexpr int DungeonKey = 25410;
|
||||
constexpr int BossKey = 25416;
|
||||
constexpr int EnchantedTorch = 503;
|
||||
constexpr int LightOfSeborhin = 15531;
|
||||
constexpr int IstaniFireOil = 16339;
|
||||
|
||||
// Money
|
||||
constexpr int GoldCoin = 2510;
|
||||
constexpr int GoldCoins = 2511;
|
||||
}
|
||||
}
|
||||
}
|
||||
+898
@@ -0,0 +1,898 @@
|
||||
#pragma once
|
||||
|
||||
namespace GW {
|
||||
namespace Constants {
|
||||
enum class MapID : uint32_t {
|
||||
None = 0,
|
||||
Gladiators_Arena,
|
||||
DEV_Test_Arena_1v1,
|
||||
Test_map,
|
||||
Warriors_Isle_outpost,
|
||||
Hunters_Isle_outpost,
|
||||
Wizards_Isle_outpost,
|
||||
Warriors_Isle,
|
||||
Hunters_Isle,
|
||||
Wizards_Isle,
|
||||
Bloodstone_Fen,
|
||||
The_Wilds,
|
||||
Aurora_Glade,
|
||||
Diessa_Lowlands,
|
||||
Gates_of_Kryta,
|
||||
DAlessio_Seaboard,
|
||||
Divinity_Coast,
|
||||
Talmark_Wilderness,
|
||||
The_Black_Curtain,
|
||||
Sanctum_Cay,
|
||||
Droknars_Forge_outpost,
|
||||
The_Frost_Gate,
|
||||
Ice_Caves_of_Sorrow,
|
||||
Thunderhead_Keep,
|
||||
Iron_Mines_of_Moladune,
|
||||
Borlis_Pass,
|
||||
Talus_Chute,
|
||||
Griffons_Mouth,
|
||||
The_Great_Northern_Wall,
|
||||
Fort_Ranik,
|
||||
Ruins_of_Surmia,
|
||||
Xaquang_Skyway,
|
||||
Nolani_Academy,
|
||||
Old_Ascalon,
|
||||
The_Fissure_of_Woe,
|
||||
Ember_Light_Camp_outpost,
|
||||
Grendich_Courthouse_outpost,
|
||||
Glints_Challenge_mission,
|
||||
Augury_Rock_outpost,
|
||||
Sardelac_Sanitarium_outpost,
|
||||
Piken_Square_outpost,
|
||||
Sage_Lands,
|
||||
Mamnoon_Lagoon,
|
||||
Silverwood,
|
||||
Ettins_Back,
|
||||
Reed_Bog,
|
||||
The_Falls,
|
||||
Dry_Top,
|
||||
Tangle_Root,
|
||||
Henge_of_Denravi_outpost,
|
||||
Test_Map_species_art, // "This is a debug map to allow testing of species art."
|
||||
Senjis_Corner_outpost,
|
||||
Burning_Isle_outpost,
|
||||
Tears_of_the_Fallen,
|
||||
Scoundrels_Rise,
|
||||
Lions_Arch_outpost,
|
||||
Cursed_Lands,
|
||||
Bergen_Hot_Springs_outpost,
|
||||
North_Kryta_Province,
|
||||
Nebo_Terrace,
|
||||
Majestys_Rest,
|
||||
Twin_Serpent_Lakes,
|
||||
Watchtower_Coast,
|
||||
Stingray_Strand,
|
||||
Kessex_Peak,
|
||||
DAlessio_Arena_mission,
|
||||
All_Call_Click_Point_1,
|
||||
Burning_Isle,
|
||||
Frozen_Isle,
|
||||
Nomads_Isle,
|
||||
Druids_Isle,
|
||||
Isle_of_the_Dead_guild_hall,
|
||||
The_Underworld,
|
||||
Riverside_Province,
|
||||
Tournament_6, // Shares description with HoH arena below
|
||||
The_Hall_of_Heroes_arena_mission,
|
||||
Broken_Tower_mission,
|
||||
House_zu_Heltzer_outpost,
|
||||
The_Courtyard_arena_mission,
|
||||
Unholy_Temples_mission,
|
||||
Burial_Mounds_mission,
|
||||
Ascalon_City_outpost,
|
||||
Tomb_of_the_Primeval_Kings,
|
||||
The_Vault_mission,
|
||||
The_Underworld_arena_mission,
|
||||
Ascalon_Arena,
|
||||
Sacred_Temples_mission,
|
||||
Icedome,
|
||||
Iron_Horse_Mine,
|
||||
Anvil_Rock,
|
||||
Lornars_Pass,
|
||||
Snake_Dance,
|
||||
Tascas_Demise,
|
||||
Spearhead_Peak,
|
||||
Ice_Floe,
|
||||
Witmans_Folly,
|
||||
Mineral_Springs,
|
||||
Dreadnoughts_Drift,
|
||||
Frozen_Forest,
|
||||
Travelers_Vale,
|
||||
Deldrimor_Bowl,
|
||||
Regent_Valley,
|
||||
The_Breach,
|
||||
Ascalon_Foothills,
|
||||
Pockmark_Flats,
|
||||
Dragons_Gullet,
|
||||
Flame_Temple_Corridor,
|
||||
Eastern_Frontier,
|
||||
The_Scar,
|
||||
The_Amnoon_Oasis_outpost,
|
||||
Diviners_Ascent,
|
||||
Vulture_Drifts,
|
||||
The_Arid_Sea,
|
||||
Prophets_Path,
|
||||
Salt_Flats,
|
||||
Skyward_Reach,
|
||||
Dunes_of_Despair,
|
||||
Thirsty_River,
|
||||
Elona_Reach,
|
||||
Augury_Rock_mission,
|
||||
The_Dragons_Lair,
|
||||
Perdition_Rock,
|
||||
Ring_of_Fire,
|
||||
Abaddons_Mouth,
|
||||
Hells_Precipice,
|
||||
Titans_Tears,
|
||||
Golden_Gates_mission,
|
||||
Scarred_Earth2,
|
||||
The_Eternal_Grove,
|
||||
Lutgardis_Conservatory_outpost,
|
||||
Vasburg_Armory_outpost,
|
||||
Serenity_Temple_outpost,
|
||||
Ice_Tooth_Cave_outpost,
|
||||
Beacons_Perch_outpost,
|
||||
Yaks_Bend_outpost,
|
||||
Frontier_Gate_outpost,
|
||||
Beetletun_outpost,
|
||||
Fishermens_Haven_outpost,
|
||||
Temple_of_the_Ages,
|
||||
Ventaris_Refuge_outpost,
|
||||
Druids_Overlook_outpost,
|
||||
Maguuma_Stade_outpost,
|
||||
Quarrel_Falls_outpost,
|
||||
Ascalon_Academy_outpost, // not in live game
|
||||
Gyala_Hatchery,
|
||||
The_Catacombs,
|
||||
Lakeside_County,
|
||||
The_Northlands,
|
||||
Ascalon_City_pre_searing, // ?
|
||||
Ascalon_Academy_PvP_battle_mission_1,
|
||||
Ascalon_Academy_PvP_battle_mission_2,
|
||||
Ascalon_Academy_explorable,
|
||||
Heroes_Audience_outpost,
|
||||
Seekers_Passage_outpost,
|
||||
Destinys_Gorge_outpost,
|
||||
Camp_Rankor_outpost,
|
||||
The_Granite_Citadel_outpost,
|
||||
Marhans_Grotto_outpost,
|
||||
Port_Sledge_outpost,
|
||||
Copperhammer_Mines_outpost,
|
||||
Green_Hills_County,
|
||||
Wizards_Folly,
|
||||
Regent_Valley_pre_Searing,
|
||||
The_Barradin_Estate_outpost,
|
||||
Ashford_Abbey_outpost,
|
||||
Foibles_Fair_outpost,
|
||||
Fort_Ranik_pre_Searing_outpost,
|
||||
Burning_Isle_mission,
|
||||
Druids_Isle_mission,
|
||||
|
||||
Frozen_Isle_mission = 170,
|
||||
Warriors_Isle_mission,
|
||||
Hunters_Isle_mission,
|
||||
Wizards_Isle_mission,
|
||||
Nomads_Isle_mission,
|
||||
Isle_of_the_Dead_guild_hall_mission,
|
||||
Frozen_Isle_outpost,
|
||||
Nomads_Isle_outpost,
|
||||
Druids_Isle_outpost,
|
||||
Isle_of_the_Dead_guild_hall_outpost,
|
||||
Fort_Koga_mission,
|
||||
Shiverpeak_Arena,
|
||||
Amnoon_Arena_mission,
|
||||
Deldrimor_Arena_mission,
|
||||
The_Crag_mission,
|
||||
The_Underworld_gvg_mission, // UW guild hall not in live game
|
||||
The_Underworld_guild_hall,
|
||||
The_Underworld_guild_hall_preview,
|
||||
Random_Arenas_outpost,
|
||||
Team_Arenas_outpost,
|
||||
Sorrows_Furnace,
|
||||
Grenths_Footprint,
|
||||
All_Call_Click_Point_2,
|
||||
Cavalon_outpost,
|
||||
Kaineng_Center_outpost,
|
||||
Drazach_Thicket,
|
||||
Jaya_Bluffs,
|
||||
Shenzun_Tunnels,
|
||||
Archipelagos,
|
||||
Maishang_Hills,
|
||||
Mount_Qinkai,
|
||||
Melandrus_Hope,
|
||||
Rheas_Crater,
|
||||
Silent_Surf,
|
||||
Unwaking_Waters_mission,
|
||||
Morostav_Trail,
|
||||
Deldrimor_War_Camp_outpost,
|
||||
Dragons_Thieves,
|
||||
Heroes_Crypt_mission,
|
||||
Mourning_Veil_Falls,
|
||||
Ferndale,
|
||||
Pongmei_Valley,
|
||||
Monastery_Overlook1,
|
||||
Zen_Daijun_outpost_mission,
|
||||
Minister_Chos_Estate_outpost_mission,
|
||||
Vizunah_Square_mission,
|
||||
Nahpui_Quarter_outpost_mission,
|
||||
Tahnnakai_Temple_outpost_mission,
|
||||
Arborstone_outpost_mission,
|
||||
Boreas_Seabed_outpost_mission,
|
||||
Sunjiang_District_outpost_mission,
|
||||
Fort_Aspenwood_mission,
|
||||
The_Eternal_Grove_outpost_mission,
|
||||
The_Jade_Quarry_mission,
|
||||
Gyala_Hatchery_outpost_mission,
|
||||
Raisu_Palace_outpost_mission,
|
||||
Imperial_Sanctum_outpost_mission,
|
||||
Unwaking_Waters,
|
||||
Grenz_Frontier_mission,
|
||||
The_Ancestral_Lands_mission,
|
||||
Amatz_Basin,
|
||||
Kaanai_Canyon_mission,
|
||||
Shadows_Passage,
|
||||
Raisu_Palace,
|
||||
The_Aurios_Mines,
|
||||
Panjiang_Peninsula,
|
||||
Kinya_Province,
|
||||
Haiju_Lagoon,
|
||||
Sunqua_Vale,
|
||||
Wajjun_Bazaar,
|
||||
Bukdek_Byway,
|
||||
The_Undercity,
|
||||
Shing_Jea_Monastery_outpost,
|
||||
Shing_Jea_Arena,
|
||||
Arborstone_explorable,
|
||||
Minister_Chos_Estate_explorable,
|
||||
Zen_Daijun_explorable,
|
||||
Boreas_Seabed_explorable,
|
||||
Great_Temple_of_Balthazar_outpost,
|
||||
Tsumei_Village_outpost,
|
||||
Seitung_Harbor_outpost,
|
||||
Ran_Musu_Gardens_outpost,
|
||||
Linnok_Courtyard,
|
||||
Dwayna_Vs_Grenth,
|
||||
Dwaynas_Camp,
|
||||
Grenths_Camp,
|
||||
Sunjiang_District_explorable,
|
||||
Minister_Chos_Estate_cinematic,
|
||||
Zen_Daijun_cinematic,
|
||||
The_Jade_Quarry_Kurzick_cinematic,
|
||||
Nahpui_Quarter_cinematic,
|
||||
Tahnnaka_Temple_cinematic,
|
||||
Arborstone_cinematic,
|
||||
Boreas_Seabed_cinematic,
|
||||
Sunjiang_District_cinematic,
|
||||
Nahpui_Quarter_explorable,
|
||||
Urgozs_Warren,
|
||||
The_Eternal_Grove_cinematic,
|
||||
Gyala_Hatchery_cinematic,
|
||||
Tahnnakai_Temple_explorable,
|
||||
Raisu_Palace_cinematic,
|
||||
Imperial_Sanctum_cinematic,
|
||||
Altrumm_Ruins,
|
||||
Zos_Shivros_Channel,
|
||||
Dragons_Throat,
|
||||
Isle_of_Weeping_Stone_outpost,
|
||||
Isle_of_Jade_outpost,
|
||||
Harvest_Temple_outpost,
|
||||
Breaker_Hollow_outpost,
|
||||
Leviathan_Pits_outpost,
|
||||
Isle_of_the_Nameless,
|
||||
Zaishen_Challenge_outpost,
|
||||
Zaishen_Elite_outpost,
|
||||
Maatu_Keep_outpost,
|
||||
Zin_Ku_Corridor_outpost,
|
||||
Monastery_Overlook2,
|
||||
Brauer_Academy_outpost,
|
||||
Durheim_Archives_outpost,
|
||||
Bai_Paasu_Reach_outpost,
|
||||
Seafarers_Rest_outpost,
|
||||
Bejunkan_Pier,
|
||||
Vizunah_Square_Local_Quarter_outpost,
|
||||
Vizunah_Square_Foreign_Quarter_outpost,
|
||||
Fort_Aspenwood_Luxon_outpost,
|
||||
Fort_Aspenwood_Kurzick_outpost,
|
||||
The_Jade_Quarry_Luxon_outpost,
|
||||
The_Jade_Quarry_Kurzick_outpost,
|
||||
Unwaking_Waters_Luxon_outpost,
|
||||
Unwaking_Waters_Kurzick_outpost,
|
||||
Saltspray_Beach_mission,
|
||||
Etnaran_Keys_mission,
|
||||
Raisu_Pavilion,
|
||||
Kaineng_Docks,
|
||||
The_Marketplace_outpost,
|
||||
Vizunah_Square_Local_Quarter_cinematic,
|
||||
Vizunah_Square_Foreign_Quarter_cinematic,
|
||||
The_Jade_Quarry_Luxon_cinematic,
|
||||
The_Deep,
|
||||
Ascalon_Arena_mission,
|
||||
Annihilation_mission,
|
||||
Kill_Count_Training_mission,
|
||||
Priest_Annihilation_Training,
|
||||
Obelisk_Annihilation_Training_mission,
|
||||
Saoshang_Trail,
|
||||
Shiverpeak_Arena_mission,
|
||||
|
||||
// The boat map icon for cross-campaign travel. NF one is later
|
||||
Travel_Battle_Isles,
|
||||
Travel_Tyria,
|
||||
Travel_Cantha,
|
||||
|
||||
// Zaishen battles
|
||||
DAlessio_Arena_mission3 = 318,
|
||||
Amnoon_Arena_mission3,
|
||||
Fort_Koga_mission3,
|
||||
Heroes_Crypt_mission3,
|
||||
Shiverpeak_Arena_mission3,
|
||||
|
||||
Fort_Aspenwood_Kurzick_cinematic,
|
||||
Fort_Aspenwood_Luxon_cinematic,
|
||||
The_Harvest_Ceremony_Kurzick_cinematic, // same cinematic but different teleport destination
|
||||
The_Harvest_Ceremony_Luxon_cinematic, // same cinematic but different teleport destination
|
||||
Imperial_Sanctum_explorable,
|
||||
Saltspray_Beach_Luxon_outpost,
|
||||
Saltspray_Beach_Kurzick_outpost,
|
||||
Heroes_Ascent_outpost,
|
||||
Grenz_Frontier_Luxon_outpost,
|
||||
Grenz_Frontier_Kurzick_outpost,
|
||||
The_Ancestral_Lands_Luxon_outpost,
|
||||
The_Ancestral_Lands_Kurzick_outpost,
|
||||
Etnaran_Keys_Luxon_outpost,
|
||||
Etnaran_Keys_Kurzick_outpost,
|
||||
Kaanai_Canyon_Luxon_outpost,
|
||||
Kaanai_Canyon_Kurzick_outpost,
|
||||
DAlessio_Arena_mission2,
|
||||
Amnoon_Arena_mission2,
|
||||
Fort_Koga_mission2,
|
||||
Heroes_Crypt_mission2,
|
||||
Shiverpeak_Arena_mission2,
|
||||
The_Hall_of_Heroes,
|
||||
The_Courtyard,
|
||||
Scarred_Earth,
|
||||
The_Underworld_PvP,
|
||||
Tanglewood_Copse_outpost,
|
||||
Saint_Anjekas_Shrine_outpost,
|
||||
Eredon_Terrace_outpost,
|
||||
Divine_Path,
|
||||
Brawlers_Pit_mission,
|
||||
Petrified_Arena_mission,
|
||||
Seabed_Arena_mission,
|
||||
Isle_of_Weeping_Stone_mission,
|
||||
Isle_of_Jade_mission,
|
||||
Imperial_Isle_mission,
|
||||
Isle_of_Meditation_mission,
|
||||
Imperial_Isle_outpost,
|
||||
Isle_of_Meditation_outpost,
|
||||
Isle_of_Weeping_Stone,
|
||||
Isle_of_Jade,
|
||||
Imperial_Isle,
|
||||
Isle_of_Meditation,
|
||||
Random_Arenas_Test,
|
||||
Shing_Jea_Arena_mission,
|
||||
All_Skills, // "This is a debug map which forces download of all skill effects"
|
||||
Dragon_Arena,
|
||||
Jahai_Bluffs,
|
||||
Kamadan_mission,
|
||||
Marga_Coast,
|
||||
Fahranur_mission,
|
||||
Sunward_Marches,
|
||||
Vortex_Elona, // Vortex travel icon on the Elona world map
|
||||
Barbarous_Shore,
|
||||
Camp_Hojanu_outpost,
|
||||
Bahdok_Caverns,
|
||||
Wehhan_Terraces_outpost,
|
||||
Dejarin_Estate,
|
||||
Arkjok_Ward,
|
||||
Yohlon_Haven_outpost,
|
||||
Gandara_the_Moon_Fortress,
|
||||
Vortex_Realm_of_Torment, // Vortex travel icon on the Realm of Torment world map
|
||||
The_Floodplain_of_Mahnkelon,
|
||||
Lions_Arch_Sunspears_in_Kryta,
|
||||
Turais_Procession,
|
||||
Sunspear_Sanctuary_outpost,
|
||||
Aspenwood_Gate_Kurzick_outpost,
|
||||
Aspenwood_Gate_Luxon_outpost,
|
||||
Jade_Flats_Kurzick_outpost,
|
||||
Jade_Flats_Luxon_outpost,
|
||||
Yatendi_Canyons,
|
||||
Chantry_of_Secrets_outpost,
|
||||
Garden_of_Seborhin,
|
||||
Holdings_of_Chokhin,
|
||||
Mihanu_Township_outpost,
|
||||
Vehjin_Mines,
|
||||
Basalt_Grotto_outpost,
|
||||
Forum_Highlands,
|
||||
Kaineng_Center_Sunspears_in_Cantha,
|
||||
Sebelkeh_Basilica, // Not in live game
|
||||
Resplendent_Makuun,
|
||||
Honur_Hill_outpost,
|
||||
Wilderness_of_Bahdza,
|
||||
Sun_Docks_cinematic, // Arriving in Elona?
|
||||
Vehtendi_Valley,
|
||||
Yahnur_Market_outpost,
|
||||
|
||||
// 408-412 are explorable maps all called "Here Be Dragons"
|
||||
|
||||
The_Hidden_City_of_Ahdashim = 413,
|
||||
The_Kodash_Bazaar_outpost,
|
||||
Lions_Gate,
|
||||
Monastery_Overlook_cinematic, // Factions opening cutscene
|
||||
Bejunkan_Pier_cinematic,
|
||||
Lions_Gate_cinematic,
|
||||
The_Mirror_of_Lyss,
|
||||
Secure_the_Refuge,
|
||||
Venta_Cemetery,
|
||||
Kamadan_Jewel_of_Istan_explorable,
|
||||
The_Tribunal,
|
||||
Kodonur_Crossroads,
|
||||
Rilohn_Refuge,
|
||||
Pogahn_Passage,
|
||||
Moddok_Crevice,
|
||||
Tihark_Orchard,
|
||||
Consulate,
|
||||
Plains_of_Jarin,
|
||||
Sunspear_Great_Hall_outpost,
|
||||
Cliffs_of_Dohjok,
|
||||
Dzagonur_Bastion,
|
||||
Dasha_Vestibule,
|
||||
Grand_Court_of_Sebelkeh,
|
||||
Command_Post,
|
||||
Jokos_Domain,
|
||||
Bone_Palace_outpost,
|
||||
The_Ruptured_Heart,
|
||||
The_Mouth_of_Torment_outpost,
|
||||
The_Shattered_Ravines,
|
||||
Lair_of_the_Forgotten_outpost,
|
||||
Poisoned_Outcrops,
|
||||
The_Sulfurous_Wastes,
|
||||
The_Ebony_Citadel_of_Mallyx_mission,
|
||||
The_Alkali_Pan,
|
||||
A_Land_of_Heroes,
|
||||
Crystal_Overlook,
|
||||
Kamadan_Jewel_of_Istan_outpost,
|
||||
Gate_of_Torment_outpost,
|
||||
Gate_of_Anguish_elite_mission,
|
||||
Secure_the_Refuge_cinematic,
|
||||
Evacuation_cinematic,
|
||||
Test_Map_solo_areas, // "This is a debug map to allow multiplayer testing of current solo areas."
|
||||
Nightfallen_Garden,
|
||||
Churrhir_Fields,
|
||||
Beknur_Harbor_outpost,
|
||||
Kodonur_Crossroads_cinematic,
|
||||
Rilohn_Refuge_cinematic,
|
||||
Pogahn_Passage_cinematic,
|
||||
The_Underworld2,
|
||||
Heart_of_Abaddon,
|
||||
The_Underworld3,
|
||||
Nightfallen_Coast,
|
||||
Nightfallen_Jahai,
|
||||
Depths_of_Madness,
|
||||
Rollerbeetle_Racing,
|
||||
Domain_of_Fear,
|
||||
Gate_of_Fear_outpost,
|
||||
Domain_of_Pain,
|
||||
Bloodstone_Fen_quest,
|
||||
Domain_of_Secrets,
|
||||
Gate_of_Secrets_outpost,
|
||||
Domain_of_Anguish,
|
||||
Ooze_Pit_mission,
|
||||
Jennurs_Horde,
|
||||
Nundu_Bay,
|
||||
Gate_of_Desolation,
|
||||
Champions_Dawn_outpost,
|
||||
Ruins_of_Morah,
|
||||
Fahranur_The_First_City,
|
||||
Bjora_Marches,
|
||||
Zehlon_Reach,
|
||||
Lahtenda_Bog,
|
||||
Arbor_Bay,
|
||||
Issnur_Isles,
|
||||
Beknur_Harbor,
|
||||
Mehtani_Keys,
|
||||
Kodlonu_Hamlet_outpost,
|
||||
Island_of_Shehkah,
|
||||
Jokanur_Diggings,
|
||||
Blacktide_Den,
|
||||
Consulate_Docks,
|
||||
Gate_of_Pain,
|
||||
Gate_of_Madness,
|
||||
Abaddons_Gate,
|
||||
Sunspear_Arena,
|
||||
Travel_Elona, // Boat travel icon in Elona
|
||||
Ice_Cliff_Chasms,
|
||||
Bokka_Amphitheatre,
|
||||
Riven_Earth,
|
||||
The_Astralarium_outpost,
|
||||
Throne_of_Secrets,
|
||||
Churranu_Island_Arena_mission,
|
||||
Shing_Jea_Monastery_mission,
|
||||
Haiju_Lagoon_mission,
|
||||
Jaya_Bluffs_mission,
|
||||
Seitung_Harbor_mission,
|
||||
Tsumei_Village_mission,
|
||||
Seitung_Harbor_mission_2,
|
||||
Tsumei_Village_mission_2,
|
||||
Minister_Chos_Estate_mission_2,
|
||||
Drakkar_Lake,
|
||||
Island_of_Shehkah_cinematic, // Nightfall opening cutscene
|
||||
Jokanur_Diggings_cinematic,
|
||||
Blacktide_Den_cinematic,
|
||||
Consulate_Docks_cinematic,
|
||||
Tihark_Orchard_cinematic,
|
||||
Dzagonur_Bastion_cinematic,
|
||||
Hidden_City_of_Ahdashim_cinematic,
|
||||
Grand_Court_of_Sebelkeh_cinematic,
|
||||
Jennurs_Horde_cinematic,
|
||||
Nundu_Bay_cinematic,
|
||||
Gates_of_Desolation_cinematic,
|
||||
Ruins_of_Morah_cinematic,
|
||||
Domain_of_Pain_cinematic,
|
||||
Gate_of_Madness_cinematic,
|
||||
Abaddons_Gate_cinematic,
|
||||
Uncharted_Isle_outpost,
|
||||
Isle_of_Wurms_outpost,
|
||||
Uncharted_Isle,
|
||||
Isle_of_Wurms,
|
||||
Uncharted_Isle_mission,
|
||||
Isle_of_Wurms_mission,
|
||||
Ahmtur_Arena_mission, // Not in live game
|
||||
Sunspear_Arena_mission,
|
||||
Corrupted_Isle_outpost,
|
||||
Isle_of_Solitude_outpost,
|
||||
Corrupted_Isle,
|
||||
Isle_of_Solitude,
|
||||
Corrupted_Isle_mission,
|
||||
Isle_of_Solitude_mission,
|
||||
Sun_Docks,
|
||||
Chahbek_Village,
|
||||
Remains_of_Sahlahja,
|
||||
Jaga_Moraine,
|
||||
Bombardment_mission,
|
||||
Norrhart_Domains,
|
||||
Hero_Battles_outpost,
|
||||
The_Beachhead_mission,
|
||||
The_Crossing_mission,
|
||||
Desert_Sands_mission,
|
||||
Varajar_Fells,
|
||||
Dajkah_Inlet,
|
||||
The_Shadow_Nexus,
|
||||
Chahbek_Village_cutscene,
|
||||
Throne_Of_Secrets_outpost, // Not in live game
|
||||
Sparkfly_Swamp,
|
||||
Gate_of_the_Nightfallen_Lands_outpost,
|
||||
Cathedral_of_Flames_Level_1,
|
||||
The_Troubled_Keeper,
|
||||
|
||||
// Landmarks on the Elona world map
|
||||
Fortress_of_Jahai,
|
||||
Halls_of_Chokhin,
|
||||
Citadel_of_Dzagon,
|
||||
Dynastic_Tombs,
|
||||
|
||||
Verdant_Cascades,
|
||||
Cathedral_of_Flames_Level_2,
|
||||
Cathedral_of_Flames_Level_3,
|
||||
Magus_Stones,
|
||||
Catacombs_of_Kathandrax_Level_1,
|
||||
Catacombs_of_Kathandrax_Level_2,
|
||||
Alcazia_Tangle,
|
||||
Rragars_Menagerie_Level_1,
|
||||
Rragars_Menagerie_Level_2,
|
||||
Rragars_Menagerie_Level_3,
|
||||
Ooze_Pit,
|
||||
Slavers_Exile_Level_1,
|
||||
Oolas_Lab_Level_1,
|
||||
Oolas_Lab_Level_2,
|
||||
Oolas_Lab_Level_3,
|
||||
Shards_of_Orr_Level_1,
|
||||
Shards_of_Orr_Level_2,
|
||||
Shards_of_Orr_Level_3,
|
||||
Arachnis_Haunt_Level_1,
|
||||
Arachnis_Haunt_Level_2,
|
||||
|
||||
// 586-591 are all dungeon maps called "TEMP"
|
||||
|
||||
Five_Team_Test = 592, // "5 team test"
|
||||
Fetid_River_mission,
|
||||
Overlook_mission, // Heroes Ascent unused/prototype map
|
||||
Cemetery_mission, // Heroes Ascent unused/prototype map
|
||||
Forgotten_Shrines_mission,
|
||||
Track_mission, // Heroes Ascent unused/prototype map
|
||||
Antechamber_mission,
|
||||
Collision_mission, // Heroes Ascent unused/prototype map
|
||||
The_Hall_of_Heroes2, // Actual HA hall of heroes? Unused?
|
||||
|
||||
// 601-603 are all dungeon maps called "TEMP"
|
||||
|
||||
Vloxen_Excavations_Level_1 = 604,
|
||||
Vloxen_Excavations_Level_2,
|
||||
Vloxen_Excavations_Level_3,
|
||||
Heart_of_the_Shiverpeaks_Level_1,
|
||||
Heart_of_the_Shiverpeaks_Level_2,
|
||||
Heart_of_the_Shiverpeaks_Level_3,
|
||||
|
||||
// 610,611 are dungeon maps with no name
|
||||
|
||||
Bloodstone_Caves_Level_1 = 612,
|
||||
Bloodstone_Caves_Level_2,
|
||||
Bloodstone_Caves_Level_3,
|
||||
Bogroot_Growths_Level_1,
|
||||
Bogroot_Growths_Level_2,
|
||||
Ravens_Point_Level_1,
|
||||
Ravens_Point_Level_2,
|
||||
Ravens_Point_Level_3,
|
||||
Slavers_Exile_Level_2,
|
||||
Slavers_Exile_Level_3,
|
||||
Slavers_Exile_Level_4,
|
||||
Slavers_Exile_Level_5,
|
||||
Vloxs_Falls,
|
||||
Battledepths_Level_1,
|
||||
Battledepths_Level_2,
|
||||
Battledepths_Level_3,
|
||||
Sepulchre_of_Dragrimmar_Level_1,
|
||||
Sepulchre_of_Dragrimmar_Level_2,
|
||||
Frostmaws_Burrows_Level_1,
|
||||
Frostmaws_Burrows_Level_2,
|
||||
Frostmaws_Burrows_Level_3,
|
||||
Frostmaws_Burrows_Level_4,
|
||||
Frostmaws_Burrows_Level_5,
|
||||
Darkrime_Delves_Level_1,
|
||||
Darkrime_Delves_Level_2,
|
||||
Darkrime_Delves_Level_3,
|
||||
Gadds_Encampment_outpost,
|
||||
Umbral_Grotto_outpost,
|
||||
Rata_Sum_outpost,
|
||||
Tarnished_Haven_outpost,
|
||||
Eye_of_the_North_outpost,
|
||||
Sifhalla_outpost,
|
||||
Gunnars_Hold_outpost,
|
||||
Olafstead_outpost,
|
||||
Hall_of_Monuments,
|
||||
Dalada_Uplands,
|
||||
Doomlore_Shrine_outpost,
|
||||
Grothmar_Wardowns,
|
||||
Longeyes_Ledge_outpost,
|
||||
Sacnoth_Valley,
|
||||
Central_Transfer_Chamber_outpost,
|
||||
Curse_of_the_Nornbear,
|
||||
Blood_Washes_Blood,
|
||||
A_Gate_Too_Far_Level_1,
|
||||
A_Gate_Too_Far_Level_2,
|
||||
A_Gate_Too_Far_Level_3,
|
||||
The_Elusive_Golemancer_Level_1,
|
||||
The_Elusive_Golemancer_Level_2,
|
||||
The_Elusive_Golemancer_Level_3,
|
||||
Finding_the_Bloodstone_Level_1,
|
||||
Finding_the_Bloodstone_Level_2,
|
||||
Finding_the_Bloodstone_Level_3,
|
||||
Genius_Operated_Living_Enchanted_Manifestation,
|
||||
Against_the_Charr,
|
||||
Warband_of_Brothers_Level_1,
|
||||
Warband_of_Brothers_Level_2,
|
||||
Warband_of_Brothers_Level_3,
|
||||
Assault_on_the_Stronghold,
|
||||
Destructions_Depths_Level_1,
|
||||
Destructions_Depths_Level_2,
|
||||
Destructions_Depths_Level_3,
|
||||
A_Time_for_Heroes,
|
||||
Warband_Training,
|
||||
Boreal_Station_outpost,
|
||||
Catacombs_of_Kathandrax_Level_3,
|
||||
Hall_of_Primordus, // Unused explorable area
|
||||
Attack_of_the_Nornbear,
|
||||
Cinematic_Cave_Norn_Cursed,
|
||||
Cinematic_Steppe_Interrogation,
|
||||
Cinematic_Interior_Research,
|
||||
Cinematic_Eye_Vision_A,
|
||||
Cinematic_Eye_Vision_B,
|
||||
Cinematic_Eye_Vision_C,
|
||||
Cinematic_Eye_Vision_D,
|
||||
Polymock_Coliseum,
|
||||
Polymock_Glacier,
|
||||
Polymock_Crossing,
|
||||
Cinematic_Mountain_Resolution,
|
||||
Cold_as_Ice,
|
||||
Beneath_Lions_Arch,
|
||||
Tunnels_Below_Cantha,
|
||||
Caverns_Below_Kamadan,
|
||||
Cinematic_Mountain_Dwarfs,
|
||||
Service_In_Defense_of_the_Eye,
|
||||
Mano_a_Norn_o,
|
||||
Service_Practice_Dummy,
|
||||
Hero_Tutorial,
|
||||
Prototype_Map,
|
||||
The_Norn_Fighting_Tournament = 700,
|
||||
Secret_Lair_of_the_Snowmen,
|
||||
Norn_Brawling_Championship,
|
||||
Kilroys_Punchout_Training,
|
||||
Fronis_Irontoes_Lair_mission,
|
||||
The_Justiciars_End,
|
||||
Designer_Test_Map,
|
||||
The_Great_Norn_Alemoot,
|
||||
Varajar_Fells_Bear_Club_quest,
|
||||
The_Crossing_mission2, // Unused RA arena?
|
||||
Epilogue,
|
||||
Insidious_Remnants,
|
||||
The_Beachhead_mission2, // Unused RA arena?
|
||||
Bombardment_mission2, // Unused RA arena?
|
||||
Desert_Sands_mission2, // Unused RA arena?
|
||||
MISSION_CINEMATIC_MISSION_PACK_TYRIA_INTRODUCTION,
|
||||
The_Battlefield_cinematic,
|
||||
Attack_on_Jaliss_Camp,
|
||||
The_Hierophants_Stronghold_cinematic,
|
||||
The_Asura_Plan_cinematic,
|
||||
Creature_Test_Map,
|
||||
Costume_Brawl_outpost,
|
||||
Whitefury_Rapids_mission,
|
||||
Kysten_Shore_mission,
|
||||
Deepway_Ruins_mission,
|
||||
Plikkup_Works_mission,
|
||||
Kilroys_Punchout_Tournament,
|
||||
Special_Ops_Flame_Temple_Corridor,
|
||||
Special_Ops_Dragons_Gullet,
|
||||
Special_Ops_Grendich_Courthouse,
|
||||
|
||||
// Cinematics replayed at the Scrying Pool in Hall of Monuments
|
||||
Encounter_in_the_Depths_hom_cinematic,
|
||||
Into_the_North_hom_cinematic,
|
||||
Arrival_at_the_Eye_hom_cinematic,
|
||||
Joras_Curse_hom_cinematic,
|
||||
The_Nornbear_hom_cinematic,
|
||||
Blood_Washes_Blood_hom_cinematic,
|
||||
Joras_Redemption_hom_cinematic,
|
||||
Sign_of_the_Raven_hom_cinematic,
|
||||
Olaf_and_Ogden_hom_cinematic,
|
||||
Audience_with_the_King_hom_cinematic,
|
||||
The_Battlefield_hom_cinematic,
|
||||
The_Charr_Prisoner_hom_cinematic,
|
||||
The_Warband_hom_cinematic,
|
||||
Questions_and_Answers_hom_cinematic,
|
||||
The_Hierophants_Stronghold_hom_cinematic,
|
||||
Revolution_hom_cinematic,
|
||||
The_Asura_Plan_hom_cinematic,
|
||||
Bookah_hom_cinematic,
|
||||
Oola_hom_cinematic,
|
||||
Gadd_hom_cinematic,
|
||||
At_the_Bloodstone_hom_cinematic,
|
||||
Before_the_Battle_hom_cinematic,
|
||||
Price_of_Victory_hom_cinematic,
|
||||
The_Great_Dwarf_hom_cinematic,
|
||||
The_Great_Destroyer_hom_cinematic,
|
||||
Ogdens_Benediction_hom_cinematic,
|
||||
|
||||
// EotN map travel icons
|
||||
Asura_Gate_Tyria,
|
||||
Asura_Gate_Cantha,
|
||||
Asura_Gate_Elona,
|
||||
|
||||
// "Mission" maps, used for icon status on world map
|
||||
Finding_the_Bloodstone_mission,
|
||||
Genius_Operated_Living_Enchanted_Manifestation_mission,
|
||||
Against_the_Charr_mission,
|
||||
Warband_of_brothers_mission,
|
||||
Assault_on_the_Stronghold_mission,
|
||||
Destructions_Depths_mission,
|
||||
A_Time_for_Heroes_mission,
|
||||
Curse_of_the_Nornbear_mission,
|
||||
Blood_Washes_Blood_mission,
|
||||
A_Gate_Too_Far_mission,
|
||||
The_Elusive_Golemancer_mission,
|
||||
The_Tengu_Accords,
|
||||
The_Battle_of_Jahai,
|
||||
The_Flight_North,
|
||||
The_Rise_of_the_White_Mantle,
|
||||
Battle_Isles_Marketplace, // Xunlai Marketplace?
|
||||
MISSION_CINEMATIC_MISSION_PACK_CANTHA_INTRODUCTION,
|
||||
Mission_Pack_Test,
|
||||
MISSION_CINEMATIC_MISSION_PACK_ELONA_INTRODUCTION,
|
||||
MISSION_CINEMATIC_MISSION_PACK_GWX_INTRODUCTION,
|
||||
Piken_Square_pre_Searing_outpost,
|
||||
|
||||
// Map 780 has invalid continent, name and description
|
||||
|
||||
Secret_Lair_of_the_Snowmen2 = 781, // ?
|
||||
Secret_Lair_of_the_Snowmen3, // ?
|
||||
Droknars_Forge_cinematic, // ?
|
||||
Isle_of_the_Nameless_PvP,
|
||||
Rollerbeetle_Racing_HeroBattles,
|
||||
Dragon_Arena_gvg,
|
||||
Dwayna_vs_Grenth_gvg,
|
||||
Temple_of_the_Ages_ROX,
|
||||
Wajjun_Bazaar_POX,
|
||||
Bokka_Amphitheatre_NOX,
|
||||
Secret_Underground_Lair,
|
||||
Golem_Tutorial_Simulation,
|
||||
Snowball_Dominance,
|
||||
Zaishen_Menagerie_Grounds,
|
||||
Zaishen_Menagerie_outpost,
|
||||
Codex_Arena_outpost,
|
||||
|
||||
// Maps 797-805 are dungeon maps with the name "..."
|
||||
|
||||
The_Underworld_Something_Wicked_This_Way_Comes = 806,
|
||||
The_Underworld_Dont_Fear_the_Reapers,
|
||||
Lions_Arch_Halloween_outpost,
|
||||
Lions_Arch_Wintersday_outpost,
|
||||
Lions_Arch_Canthan_New_Year_outpost,
|
||||
Ascalon_City_Wintersday_outpost,
|
||||
Droknars_Forge_Halloween_outpost,
|
||||
Droknars_Forge_Wintersday_outpost,
|
||||
Tomb_of_the_Primeval_Kings_Halloween_outpost,
|
||||
Shing_Jea_Monastery_Dragon_Festival_outpost,
|
||||
Shing_Jea_Monastery_Canthan_New_Year_outpost,
|
||||
Kaineng_Center_Canthan_New_Year_outpost,
|
||||
Kamadan_Jewel_of_Istan_Halloween_outpost,
|
||||
Kamadan_Jewel_of_Istan_Wintersday_outpost,
|
||||
Kamadan_Jewel_of_Istan_Canthan_New_Year_outpost,
|
||||
Eye_of_the_North_outpost_Wintersday_outpost,
|
||||
Tester_HUB,
|
||||
|
||||
DAlessio_Arena_mission4,
|
||||
Amnoon_Arena_mission4,
|
||||
Churranu_Island_Arena_mission2,
|
||||
Fort_Koga_mission4,
|
||||
Petrified_Arena_mission2,
|
||||
Heroes_Crypt_mission4,
|
||||
Seabed_Arena_mission2,
|
||||
Deldrimor_Arena_mission2,
|
||||
Brawlers_Pit_mission2,
|
||||
The_Crag_mission2,
|
||||
Sunspear_Arena_mission2,
|
||||
Shing_Jea_Arena_mission2,
|
||||
Ascalon_Arena_mission2,
|
||||
Shiverpeak_Arena_mission4,
|
||||
|
||||
War_in_Kryta_Talmark_Wilderness,
|
||||
War_in_Kryta_Trial_of_Zinn,
|
||||
War_in_Kryta_Divinity_Coast,
|
||||
War_in_Kryta_Lions_Arch_Keep,
|
||||
War_in_Kryta_DAlessio_Seaboard,
|
||||
War_in_Kryta_The_Battle_for_Lions_Arch,
|
||||
War_in_Kryta_Riverside_Province,
|
||||
War_in_Kryta_Lions_Arch,
|
||||
War_in_Kryta_The_Mausoleum,
|
||||
War_in_Kryta_Rise,
|
||||
War_in_Kryta_Shadows_in_the_Jungle,
|
||||
War_in_Kryta_A_Vengeance_of_Blades,
|
||||
War_in_Kryta_Auspicious_Beginnings,
|
||||
Beetletun_explorable, // Is this part of War in Kryta? or Rise?
|
||||
|
||||
// War in Kryta? Festival event quests?
|
||||
Aurora_Glade2, // explorable
|
||||
Majestys_Rest2,
|
||||
Watchtower_Coast2,
|
||||
|
||||
Olafstead_cinematic,
|
||||
The_Great_Snowball_Fight_of_the_Gods__Operation_Crush_Spirits,
|
||||
The_Great_Snowball_Fight_of_the_Gods__Fighting_in_a_Winter_Wonderland,
|
||||
Embark_Beach,
|
||||
Regent_Valley_1059_AE,
|
||||
Lakeside_County_1059_AE,
|
||||
Dragons_Throat_area__What_Waits_in_Shadow = 860,
|
||||
Kaineng_Center_Winds_of_Change__A_Chance_Encounter,
|
||||
The_Marketplace_area__Tracking_the_Corruption,
|
||||
Bukdek_Byway_Winds_of_Change__Cantha_Courier_Crisis,
|
||||
Tsumei_Village_Winds_of_Change__A_Treatys_a_Treaty,
|
||||
Seitung_Harbor_area__Deadly_Cargo,
|
||||
Tahnnakai_Temple_Winds_of_Change__The_Rescue_Attempt,
|
||||
Wajjun_Bazaar_Winds_of_Change__Violence_in_the_Streets,
|
||||
Scarred_Psyche_mission,
|
||||
Shadows_Passage_Winds_of_Change__Calling_All_Thugs,
|
||||
Altrumm_Ruins__Finding_Jinnai,
|
||||
Shing_Jea_Monastery__Raid_on_Shing_Jea_Monastery,
|
||||
Kaineng_Center_Winds_of_Change__Raid_on_Kaineng_Center,
|
||||
Wajjun_Bazaar_Winds_of_Change__Ministry_of_Oppression,
|
||||
The_Final_Confrontation,
|
||||
Lakeside_County_1070_AE,
|
||||
Ashford_Catacombs_1070_AE,
|
||||
|
||||
Count = 0x370,
|
||||
};
|
||||
}
|
||||
}
|
||||
+273
@@ -0,0 +1,273 @@
|
||||
#pragma once
|
||||
|
||||
namespace GW {
|
||||
namespace Constants {
|
||||
enum class QuestID : uint32_t {
|
||||
None = 0,
|
||||
// Underworld
|
||||
UW_Chamber = 101,
|
||||
UW_Wastes,
|
||||
UW_UWG,
|
||||
UW_Mnt,
|
||||
UW_Pits,
|
||||
UW_Planes,
|
||||
UW_Pools,
|
||||
UW_Escort,
|
||||
UW_Restore,
|
||||
UW_Vale,
|
||||
|
||||
// Fissure of woe
|
||||
Fow_Defend = 202,
|
||||
Fow_ArmyOfDarknesses,
|
||||
Fow_WailingLord,
|
||||
Fow_Griffons,
|
||||
Fow_Slaves,
|
||||
Fow_Restore,
|
||||
Fow_Hunt,
|
||||
Fow_Forgemaster,
|
||||
Fow_Tos = 211,
|
||||
Fow_Toc,
|
||||
Fow_Khobay = 224,
|
||||
|
||||
//Doa
|
||||
Doa_DeathbringerCompany = 749,
|
||||
Doa_RiftBetweenUs = 752,
|
||||
Doa_ToTheRescue = 753,
|
||||
|
||||
// city
|
||||
Doa_City = 751,
|
||||
|
||||
// Veil
|
||||
Doa_BreachingStygianVeil = 742,
|
||||
Doa_BroodWars = 755,
|
||||
|
||||
// Foundry
|
||||
Doa_FoundryBreakout = 743,
|
||||
Doa_FoundryOfFailedCreations = 744,
|
||||
|
||||
// slavers
|
||||
The_Last_Hierophant = 917,
|
||||
|
||||
// Prophecies
|
||||
ZaishenMission_The_Great_Northern_Wall = 936,
|
||||
ZaishenMission_Fort_Ranik = 937,
|
||||
ZaishenMission_Ruins_of_Surmia = 938,
|
||||
ZaishenMission_Nolani_Academy = 939,
|
||||
ZaishenMission_Borlis_Pass = 940,
|
||||
ZaishenMission_The_Frost_Gate = 941,
|
||||
ZaishenMission_Gates_of_Kryta = 942,
|
||||
ZaishenMission_DAlessio_Seaboard = 943,
|
||||
ZaishenMission_Divinity_Coast = 944,
|
||||
ZaishenMission_The_Wilds = 945,
|
||||
ZaishenMission_Bloodstone_Fen = 946,
|
||||
ZaishenMission_Aurora_Glade = 947,
|
||||
ZaishenMission_Riverside_Province = 948,
|
||||
ZaishenMission_Sanctum_Cay = 949,
|
||||
ZaishenMission_Dunes_of_Despair = 950,
|
||||
ZaishenMission_Thirsty_River = 951,
|
||||
ZaishenMission_Elona_Reach = 952,
|
||||
ZaishenMission_Augury_Rock = 953,
|
||||
ZaishenMission_The_Dragons_Lair = 954,
|
||||
ZaishenMission_Ice_Caves_of_Sorrow = 955,
|
||||
ZaishenMission_Iron_Mines_of_Moladune = 956,
|
||||
ZaishenMission_Thunderhead_Keep = 957,
|
||||
ZaishenMission_Ring_of_Fire = 958,
|
||||
ZaishenMission_Abaddons_Mouth = 959,
|
||||
ZaishenMission_Hells_Precipice = 960,
|
||||
|
||||
// Factions
|
||||
ZaishenMission_Minister_Chos_Estate = 1119,
|
||||
ZaishenMission_Zen_Daijun = 961,
|
||||
ZaishenMission_Vizunah_Square = 962,
|
||||
ZaishenMission_Nahpui_Quarter = 963,
|
||||
ZaishenMission_Tahnnakai_Temple = 964,
|
||||
ZaishenMission_Arborstone = 965,
|
||||
ZaishenMission_Boreas_Seabed = 966,
|
||||
ZaishenMission_Sunjiang_District = 967,
|
||||
ZaishenMission_The_Eternal_Grove = 968,
|
||||
ZaishenMission_Gyala_Hatchery = 970,
|
||||
ZaishenMission_Unwaking_Waters = 969,
|
||||
ZaishenMission_Raisu_Palace = 971,
|
||||
ZaishenMission_Imperial_Sanctum = 972,
|
||||
|
||||
// Nightfall
|
||||
ZaishenMission_Chahbek_Village = 978,
|
||||
ZaishenMission_Jokanur_Diggings = 979,
|
||||
ZaishenMission_Blacktide_Den = 980,
|
||||
ZaishenMission_Consulate_Docks = 981,
|
||||
ZaishenMission_Venta_Cemetery = 982,
|
||||
ZaishenMission_Kodonur_Crossroads = 983,
|
||||
ZaishenMission_Pogahn_Passage = 1181,
|
||||
ZaishenMission_Rilohn_Refuge = 984,
|
||||
ZaishenMission_Moddok_Crevice = 985,
|
||||
ZaishenMission_Tihark_Orchard = 986,
|
||||
ZaishenMission_Dasha_Vestibule = 988,
|
||||
ZaishenMission_Dzagonur_Bastion = 987,
|
||||
ZaishenMission_Grand_Court_of_Sebelkeh = 989,
|
||||
ZaishenMission_Jennurs_Horde = 990,
|
||||
ZaishenMission_Nundu_Bay = 991,
|
||||
ZaishenMission_Gate_of_Desolation = 992,
|
||||
ZaishenMission_Ruins_of_Morah = 993,
|
||||
ZaishenMission_Gate_of_Pain = 994,
|
||||
ZaishenMission_Gate_of_Madness = 995,
|
||||
ZaishenMission_Abaddons_Gate = 996,
|
||||
|
||||
// Eye of the North
|
||||
ZaishenMission_Finding_the_Bloodstone = 1000,
|
||||
ZaishenMission_The_Elusive_Golemancer = 1001,
|
||||
ZaishenMission_G_O_L_E_M = 1002,
|
||||
ZaishenMission_Against_the_Charr = 1003,
|
||||
ZaishenMission_Warband_of_Brothers = 1004,
|
||||
ZaishenMission_Assault_on_the_Stronghold = 1005,
|
||||
ZaishenMission_Curse_of_the_Nornbear = 1006,
|
||||
ZaishenMission_A_Gate_Too_Far = 1008,
|
||||
ZaishenMission_Blood_Washes_Blood = 1007,
|
||||
ZaishenMission_Destructions_Depths = 1009,
|
||||
ZaishenMission_A_Time_for_Heroes = 1010,
|
||||
|
||||
ZaishenBounty_Urgoz = 1025,
|
||||
ZaishenBounty_Ilsundur_Lord_of_Fire = 1048,
|
||||
ZaishenBounty_Chung_The_Attuned = 1026,
|
||||
ZaishenBounty_Mungri_Magicbox = 1029,
|
||||
ZaishenBounty_The_Stygian_Lords = 1046,
|
||||
ZaishenBounty_Rragar_Maneater = 1049,
|
||||
ZaishenBounty_Murakai_Lady_of_the_Night = 1050,
|
||||
ZaishenBounty_Prismatic_Ooze = 1051,
|
||||
ZaishenBounty_Havok_Soulwail = 1052,
|
||||
ZaishenBounty_Frostmaw_the_Kinslayer = 1053,
|
||||
ZaishenBounty_Remnant_of_Antiquities = 1054,
|
||||
ZaishenBounty_Plague_of_Destruction = 1055,
|
||||
ZaishenBounty_Zoldark_the_Unholy = 1056,
|
||||
ZaishenBounty_Khabuus = 1057,
|
||||
ZaishenBounty_Zhim_Monns = 1058,
|
||||
ZaishenBounty_Eldritch_Ettin = 1059,
|
||||
ZaishenBounty_Fendi_Nin = 1060,
|
||||
ZaishenBounty_TPS_Regulator_Golem = 1061,
|
||||
ZaishenBounty_Arachni = 1062,
|
||||
ZaishenBounty_Forgewight = 1063,
|
||||
ZaishenBounty_Selvetarm = 1064,
|
||||
ZaishenBounty_Justiciar_Thommis = 1065,
|
||||
ZaishenBounty_Rand_Stormweaver = 1066,
|
||||
ZaishenBounty_Duncan_the_Black = 1067,
|
||||
ZaishenBounty_Fronis_Irontoe = 1068,
|
||||
ZaishenBounty_Magmus = 1070,
|
||||
ZaishenBounty_Lord_Khobay = 1086,
|
||||
|
||||
ZaishenVanquish_Dejarin_Estate = 1201,
|
||||
ZaishenVanquish_Watchtower_Coast = 1202,
|
||||
ZaishenVanquish_Arbor_Bay = 1203,
|
||||
ZaishenVanquish_Barbarous_Shore = 1204,
|
||||
ZaishenVanquish_Deldrimor_Bowl = 1205,
|
||||
ZaishenVanquish_Boreas_Seabed = 1206,
|
||||
ZaishenVanquish_Cliffs_of_Dohjok = 1207,
|
||||
ZaishenVanquish_Diessa_Lowlands = 1208,
|
||||
ZaishenVanquish_Bukdek_Byway = 1209,
|
||||
ZaishenVanquish_Bjora_Marches = 1210,
|
||||
ZaishenVanquish_Crystal_Overlook = 1211,
|
||||
ZaishenVanquish_Diviners_Ascent = 1212,
|
||||
ZaishenVanquish_Dalada_Uplands = 1213,
|
||||
ZaishenVanquish_Drazach_Thicket = 1214,
|
||||
ZaishenVanquish_Fahranur_the_First_City = 1215,
|
||||
ZaishenVanquish_Dragons_Gullet = 1216,
|
||||
ZaishenVanquish_Ferndale = 1217,
|
||||
ZaishenVanquish_Forum_Highlands = 1218,
|
||||
ZaishenVanquish_Dreadnoughts_Drift = 1219,
|
||||
ZaishenVanquish_Drakkar_Lake = 1220,
|
||||
ZaishenVanquish_Dry_Top = 1221,
|
||||
ZaishenVanquish_Tears_of_the_Fallen = 1222,
|
||||
ZaishenVanquish_Gyala_Hatchery = 1223,
|
||||
ZaishenVanquish_Ettins_Back = 1224,
|
||||
ZaishenVanquish_Gandara_the_Moon_Fortress = 1225,
|
||||
ZaishenVanquish_Grothmar_Wardowns = 1226,
|
||||
ZaishenVanquish_Flame_Temple_Corridor = 1227,
|
||||
ZaishenVanquish_Haiju_Lagoon = 1228,
|
||||
ZaishenVanquish_Frozen_Forest = 1229,
|
||||
ZaishenVanquish_Garden_of_Seborhin = 1230,
|
||||
ZaishenVanquish_Grenths_Footprint = 1231,
|
||||
ZaishenVanquish_Jaya_Bluffs = 1232,
|
||||
ZaishenVanquish_Holdings_of_Chokhin = 1233,
|
||||
ZaishenVanquish_Ice_Cliff_Chasms = 1234,
|
||||
ZaishenVanquish_Griffons_Mouth = 1235,
|
||||
ZaishenVanquish_Kinya_Province = 1236,
|
||||
ZaishenVanquish_Issnur_Isles = 1237,
|
||||
ZaishenVanquish_Jaga_Moraine = 1238,
|
||||
ZaishenVanquish_Ice_Floe = 1239,
|
||||
ZaishenVanquish_Maishang_Hills = 1240,
|
||||
ZaishenVanquish_Jahai_Bluffs = 1241,
|
||||
ZaishenVanquish_Riven_Earth = 1242,
|
||||
ZaishenVanquish_Icedome = 1243,
|
||||
ZaishenVanquish_Minister_Chos_Estate = 1244,
|
||||
ZaishenVanquish_Mehtani_Keys = 1245,
|
||||
ZaishenVanquish_Sacnoth_Valley = 1246,
|
||||
ZaishenVanquish_Iron_Horse_Mine = 1247,
|
||||
ZaishenVanquish_Morostav_Trail = 1248,
|
||||
ZaishenVanquish_Plains_of_Jarin = 1249,
|
||||
ZaishenVanquish_Sparkfly_Swamp = 1250,
|
||||
ZaishenVanquish_Kessex_Peak = 1251,
|
||||
ZaishenVanquish_Mourning_Veil_Falls = 1252,
|
||||
ZaishenVanquish_The_Alkali_Pan = 1253,
|
||||
ZaishenVanquish_Varajar_Fells = 1254,
|
||||
ZaishenVanquish_Lornars_Pass = 1255,
|
||||
ZaishenVanquish_Pongmei_Valley = 1256,
|
||||
ZaishenVanquish_The_Floodplain_of_Mahnkelon = 1257,
|
||||
ZaishenVanquish_Verdant_Cascades = 1258,
|
||||
ZaishenVanquish_Majestys_Rest = 1259,
|
||||
ZaishenVanquish_Raisu_Palace = 1260,
|
||||
ZaishenVanquish_The_Hidden_City_of_Ahdashim = 1261,
|
||||
ZaishenVanquish_Rheas_Crater = 1262,
|
||||
ZaishenVanquish_Mamnoon_Lagoon = 1263,
|
||||
ZaishenVanquish_Shadows_Passage = 1264,
|
||||
ZaishenVanquish_The_Mirror_of_Lyss = 1265,
|
||||
ZaishenVanquish_Saoshang_Trail = 1266,
|
||||
ZaishenVanquish_Nebo_Terrace = 1267,
|
||||
ZaishenVanquish_Shenzun_Tunnels = 1268,
|
||||
ZaishenVanquish_The_Ruptured_Heart = 1269,
|
||||
ZaishenVanquish_Salt_Flats = 1270,
|
||||
ZaishenVanquish_North_Kryta_Province = 1271,
|
||||
ZaishenVanquish_Silent_Surf = 1272,
|
||||
ZaishenVanquish_The_Shattered_Ravines = 1273,
|
||||
ZaishenVanquish_Scoundrels_Rise = 1274,
|
||||
ZaishenVanquish_Old_Ascalon = 1275,
|
||||
ZaishenVanquish_Sunjiang_District = 1276,
|
||||
ZaishenVanquish_The_Sulphurous_Wastes = 1277,
|
||||
ZaishenVanquish_Magus_Stones = 1278,
|
||||
ZaishenVanquish_Perdition_Rock = 1279,
|
||||
ZaishenVanquish_Sunqua_Vale = 1280,
|
||||
ZaishenVanquish_Turais_Procession = 1281,
|
||||
ZaishenVanquish_Norrhart_Domains = 1282,
|
||||
ZaishenVanquish_Pockmark_Flats = 1283,
|
||||
ZaishenVanquish_Tahnnakai_Temple = 1284,
|
||||
ZaishenVanquish_Vehjin_Mines = 1285,
|
||||
ZaishenVanquish_Poisoned_Outcrops = 1286,
|
||||
ZaishenVanquish_Prophets_Path = 1287,
|
||||
ZaishenVanquish_The_Eternal_Grove = 1288,
|
||||
ZaishenVanquish_Tascas_Demise = 1289,
|
||||
ZaishenVanquish_Respendent_Makuun = 1290,
|
||||
ZaishenVanquish_Reed_Bog = 1291,
|
||||
ZaishenVanquish_Unwaking_Waters = 1292,
|
||||
ZaishenVanquish_Stingray_Strand = 1293,
|
||||
ZaishenVanquish_Sunward_Marches = 1294,
|
||||
ZaishenVanquish_Regent_Valley = 1295,
|
||||
ZaishenVanquish_Wajjun_Bazaar = 1296,
|
||||
ZaishenVanquish_Yatendi_Canyons = 1297,
|
||||
ZaishenVanquish_Twin_Serpent_Lakes = 1298,
|
||||
ZaishenVanquish_Sage_Lands = 1299,
|
||||
ZaishenVanquish_Xaquang_Skyway = 1300,
|
||||
ZaishenVanquish_Zehlon_Reach = 1301,
|
||||
ZaishenVanquish_Tangle_Root = 1302,
|
||||
ZaishenVanquish_Silverwood = 1303,
|
||||
ZaishenVanquish_Zen_Daijun = 1304,
|
||||
ZaishenVanquish_The_Arid_Sea = 1305,
|
||||
ZaishenVanquish_Nahpui_Quarter = 1306,
|
||||
ZaishenVanquish_Skyward_Reach = 1307,
|
||||
ZaishenVanquish_The_Scar = 1308,
|
||||
ZaishenVanquish_The_Black_Curtain = 1309,
|
||||
ZaishenVanquish_Panjiang_Peninsula = 1310,
|
||||
ZaishenVanquish_Snake_Dance = 1311,
|
||||
ZaishenVanquish_Travelers_Vale = 1312,
|
||||
ZaishenVanquish_The_Breach = 1313,
|
||||
ZaishenVanquish_Lahtenda_Bog = 1314,
|
||||
ZaishenVanquish_Spearhead_Peak = 1315
|
||||
};
|
||||
}
|
||||
}
|
||||
+3139
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,968 @@
|
||||
namespace GW {
|
||||
enum class CallTargetType : uint32_t;
|
||||
enum class WorldActionId : uint32_t;
|
||||
struct GamePos;
|
||||
struct Effect;
|
||||
struct Vec2f;
|
||||
typedef uint32_t AgentID;
|
||||
|
||||
namespace Merchant {
|
||||
enum class TransactionType : uint32_t;
|
||||
}
|
||||
namespace Constants {
|
||||
enum class Language;
|
||||
enum class MapID : uint32_t;
|
||||
enum class InstanceType;
|
||||
enum class QuestID : uint32_t;
|
||||
enum class SkillID : uint32_t;
|
||||
}
|
||||
namespace Chat {
|
||||
enum Channel : int;
|
||||
typedef uint32_t Color;
|
||||
}
|
||||
|
||||
namespace Chat {
|
||||
enum Channel : int;
|
||||
}
|
||||
namespace SkillbarMgr {
|
||||
struct SkillTemplate;
|
||||
}
|
||||
namespace UI {
|
||||
struct WindowPosition;
|
||||
enum class FlagPreference : uint32_t;
|
||||
enum class NumberPreference : uint32_t;
|
||||
enum class StringPreference : uint32_t;
|
||||
enum class EnumPreference : uint32_t;
|
||||
struct CompassPoint;
|
||||
|
||||
enum class UIMessage : uint32_t {
|
||||
kNone = 0x0,
|
||||
kFrameMessage_0x1,
|
||||
kFrameMessage_0x2,
|
||||
kFrameMessage_0x3,
|
||||
kFrameMessage_0x4,
|
||||
kFrameMessage_0x5,
|
||||
kFrameMessage_0x6,
|
||||
kFrameMessage_0x7,
|
||||
kResize, // 0x8
|
||||
kInitFrame, // 0x9
|
||||
kFrameMessage_0xa,
|
||||
kDestroyFrame, // 0xb
|
||||
kFrameDisabledChange, // wparam = is_enabled
|
||||
kFrameMessage_0xd,
|
||||
kFrameMessage_0xe,
|
||||
kFrameMessage_0xf,
|
||||
kFrameMessage_0x10,
|
||||
kFrameMessage_0x11,
|
||||
kFrameMessage_0x12,
|
||||
kFrameMessage_0x13,
|
||||
kFrameMessage_0x14,
|
||||
kFrameMessage_0x15,
|
||||
kFrameMessage_0x16,
|
||||
kFrameMessage_0x17,
|
||||
kFrameMessage_0x18,
|
||||
kFrameMessage_0x19,
|
||||
kFrameMessage_0x1a,
|
||||
kFrameMessage_0x1b,
|
||||
kFrameMessage_0x1c,
|
||||
kFrameMessage_0x1d,
|
||||
kKeyDown = 0x20, // wparam = UIPacket::kKeyAction* - Updated from 0x1e to 0x20
|
||||
kSetFocus, // 0x1f, wparam = 1 or 0
|
||||
kKeyUp, // 0x20, wparam = UIPacket::kKeyAction*
|
||||
kFrameMessage_0x21, // 0x21
|
||||
kMouseClick, // 0x22, wparam = UIPacket::kMouseClick*
|
||||
kFrameMessage_0x23, // 0x23
|
||||
kMouseCoordsClick, // 0x24, wparam = UIPacket::kMouseCoordsClick*
|
||||
kFrameMessage_0x25, // 0x25
|
||||
kMouseUp, // 0x26, wparam = UIPacket::kMouseCoordsClick*
|
||||
kFrameMessage_0x27, // 0x27
|
||||
kFrameMessage_0x28, // 0x28
|
||||
kFrameMessage_0x29, // 0x29
|
||||
kFrameMessage_0x2a, // 0x2a
|
||||
kFrameMessage_0x2b, // 0x2b
|
||||
kToggleButtonDown, // 0x2c
|
||||
kFrameMessage_0x2d, // 0x2d
|
||||
kMouseClick2 = 0x31, // 0x2e, wparam = UIPacket::kMouseAction*
|
||||
kMouseAction, // 0x2f, wparam = UIPacket::kMouseAction*
|
||||
kRenderFrame_0x30, // 0x30
|
||||
kRenderFrame_0x31 = 0x35, // 0x31
|
||||
kFrameVisibilityChanged, // 0x32, wparam = is_visible
|
||||
kSetLayout, // 0x33
|
||||
kMeasureContent, // 0x34
|
||||
kFrameMessage_0x35, // 0x35
|
||||
kFrameMessage_0x36, // 0x36
|
||||
kRefreshContent, // 0x37
|
||||
kFrameMessage_0x38,
|
||||
kFrameMessage_0x39,
|
||||
kFrameMessage_0x3a,
|
||||
kFrameMessage_0x3b,
|
||||
kFrameMessage_0x3c = 0x44,
|
||||
kFrameMessage_0x3d,
|
||||
kFrameMessage_0x3e,
|
||||
kFrameMessage_0x3f,
|
||||
kFrameMessage_0x40,
|
||||
kFrameMessage_0x41,
|
||||
kFrameMessage_0x42,
|
||||
kRenderFrame_0x43, // 0x43
|
||||
kFrameMessage_0x44 = 0x52,
|
||||
kFrameMessage_0x45,
|
||||
kFrameMessage_0x46 = 0x56,
|
||||
kFrameMessage_0x47, // 0x47, Multiple uses depending on frame
|
||||
kFrameMessage_0x48, // 0x48, Multiple uses depending on frame
|
||||
kFrameMessage_0x49, // 0x49, Multiple uses depending on frame
|
||||
kFrameMessage_0x4a, // 0x4a, Multiple uses depending on frame
|
||||
kFrameMessage_0x4b, // 0x4b, Multiple uses depending on frame
|
||||
kFrameMessage_0x4c, // 0x4c, Multiple uses depending on frame
|
||||
kFrameMessage_0x4d, // 0x4d, Multiple uses depending on frame
|
||||
kFrameMessage_0x4e, // 0x4e, Multiple uses depending on frame
|
||||
kFrameMessage_0x4f, // 0x4f, Multiple uses depending on frame
|
||||
kFrameMessage_0x50, // 0x50, Multiple uses depending on frame
|
||||
kFrameMessage_0x51, // 0x51, Multiple uses depending on frame
|
||||
kFrameMessage_0x52, // 0x52, Multiple uses depending on frame
|
||||
kFrameMessage_0x53, // 0x53, Multiple uses depending on frame
|
||||
kFrameMessage_0x54, // 0x54, Multiple uses depending on frame
|
||||
kFrameMessage_0x55, // 0x55, Multiple uses depending on frame
|
||||
kFrameMessage_0x56, // 0x56, Multiple uses depending on frame
|
||||
kFrameMessage_0x57, // 0x57, Multiple uses depending on frame
|
||||
|
||||
// High bit messages start at 0x10000000
|
||||
kMessage_0x10000000 = 0x10000000,
|
||||
kMessage_0x10000001,
|
||||
kMessage_0x10000002,
|
||||
kMessage_0x10000003,
|
||||
kMessage_0x10000004,
|
||||
kMessage_0x10000005,
|
||||
kMessage_0x10000006,
|
||||
kAgentUpdate, // 0x10000007, wparam = uint32_t agent_id
|
||||
kAgentDestroy, // 0x10000008, wparam = uint32_t agent_id
|
||||
kUpdateAgentEffects, // 0x10000009
|
||||
kMessage_0x1000000a,
|
||||
kMessage_0x1000000b,
|
||||
kDialogueMessage, // 0x1000000c
|
||||
kMessage_0x1000000d,
|
||||
kMessage_0x1000000e,
|
||||
kMessage_0x1000000f,
|
||||
kMessage_0x10000010,
|
||||
kMessage_0x10000011,
|
||||
kMessage_0x10000012,
|
||||
kMessage_0x10000013,
|
||||
kMessage_0x10000014,
|
||||
kMessage_0x10000015,
|
||||
kMessage_0x10000016,
|
||||
kAgentSpeechBubble, // 0x10000017
|
||||
kMessage_0x10000018,
|
||||
kShowAgentNameTag, // 0x10000019, wparam = AgentNameTagInfo*
|
||||
kHideAgentNameTag, // 0x1000001A
|
||||
kSetAgentNameTagAttribs, // 0x1000001B, wparam = AgentNameTagInfo*
|
||||
kMessage_0x1000001c,
|
||||
kSetAgentProfession, // 0x1000001D, wparam = UIPacket::kSetAgentProfession*
|
||||
kMessage_0x1000001e,
|
||||
kMessage_0x1000001f,
|
||||
kChangeTarget, // 0x10000020, wparam = UIPacket::kChangeTarget*
|
||||
kMessage_0x10000021,
|
||||
kMessage_0x10000022,
|
||||
kMessage_0x10000023,
|
||||
kAgentSkillActivated, // 0x10000024, kAgentSkillPacket
|
||||
kAgentSkillActivatedInstantly, // 0x10000025, kAgentSkillPacket
|
||||
kAgentSkillCancelled, // 0x10000026, kAgentSkillPacket
|
||||
kAgentSkillStartedCast, // 0x10000027, wparam = UIPacket::kAgentStartCasting*
|
||||
kMessage_0x10000028,
|
||||
kShowMapEntryMessage, // 0x10000029, wparam = { wchar_t* title, wchar_t* subtitle }
|
||||
kSetCurrentPlayerData, // 0x1000002A, fired after setting the worldcontext player name
|
||||
kMessage_0x1000002b,
|
||||
kMessage_0x1000002c,
|
||||
kMessage_0x1000002d,
|
||||
kMessage_0x1000002e,
|
||||
kMessage_0x1000002f,
|
||||
kMessage_0x10000030,
|
||||
kMessage_0x10000031,
|
||||
kMessage_0x10000032,
|
||||
kMessage_0x10000033,
|
||||
kPostProcessingEffect, // 0x10000034, Triggered when drunk. wparam = UIPacket::kPostProcessingEffect
|
||||
kMessage_0x10000035,
|
||||
kMessage_0x10000036,
|
||||
kMessage_0x10000037,
|
||||
kHeroAgentAdded, // 0x10000038, hero assigned to agent/inventory/ai mode
|
||||
kHeroDataAdded, // 0x10000039, hero info received from server (name, level etc)
|
||||
kMessage_0x1000003a,
|
||||
kMessage_0x1000003b,
|
||||
kMessage_0x1000003c,
|
||||
kMessage_0x1000003d,
|
||||
kMessage_0x1000003e,
|
||||
kMessage_0x1000003f,
|
||||
kShowXunlaiChest, // 0x10000040
|
||||
kMessage_0x10000041,
|
||||
kMessage_0x10000042,
|
||||
kMessage_0x10000043,
|
||||
kMessage_0x10000044,
|
||||
kMessage_0x10000045,
|
||||
kMinionCountUpdated, // 0x10000046
|
||||
kMoraleChange, // 0x10000047, wparam = {agent id, morale percent }
|
||||
kMessage_0x10000048,
|
||||
kMessage_0x10000049,
|
||||
kMessage_0x1000004a,
|
||||
kMessage_0x1000004b,
|
||||
kMessage_0x1000004c,
|
||||
kMessage_0x1000004d,
|
||||
kMessage_0x1000004e,
|
||||
kMessage_0x1000004f,
|
||||
kLoginStateChanged, // 0x10000050, wparam = {bool is_logged_in, bool unk }
|
||||
kMessage_0x10000051,
|
||||
kMessage_0x10000052,
|
||||
kMessage_0x10000053,
|
||||
kMessage_0x10000054,
|
||||
kEffectAdd, // 0x10000055, wparam = {agent_id, GW::Effect*}
|
||||
kEffectRenew, // 0x10000056, wparam = GW::Effect*
|
||||
kEffectRemove, // 0x10000057, wparam = effect id
|
||||
kMessage_0x10000058,
|
||||
kMessage_0x10000059,
|
||||
kMessage_0x1000005a,
|
||||
kSkillActivated, // 0x1000005b, wparam ={ uint32_t agent_id , uint32_t skill_id }
|
||||
kMessage_0x1000005c,
|
||||
kMessage_0x1000005d,
|
||||
kUpdateSkillbar, // 0x1000005E, wparam ={ uint32_t agent_id , ... }
|
||||
kUpdateSkillsAvailable, // 0x1000005f, Triggered on a skill unlock, profession change or map load
|
||||
kMessage_0x10000060,
|
||||
kMessage_0x10000061,
|
||||
kMessage_0x10000062,
|
||||
kMessage_0x10000063,
|
||||
kPlayerTitleChanged, // 0x10000064, wparam = { uint32_t player_id, uint32_t title_id }
|
||||
kTitleProgressUpdated, // 0x10000065, wparam = title_id
|
||||
kExperienceGained, // 0x10000066, wparam = experience amount
|
||||
kMessage_0x10000067,
|
||||
kMessage_0x10000068,
|
||||
kMessage_0x10000069,
|
||||
kMessage_0x1000006a,
|
||||
kMessage_0x1000006b,
|
||||
kMessage_0x1000006c,
|
||||
kMessage_0x1000006d,
|
||||
kMessage_0x1000006e,
|
||||
kMessage_0x1000006f,
|
||||
kMessage_0x10000070,
|
||||
kMessage_0x10000071,
|
||||
kMessage_0x10000072,
|
||||
kMessage_0x10000073,
|
||||
kMessage_0x10000074,
|
||||
kMessage_0x10000075,
|
||||
kMessage_0x10000076,
|
||||
kMessage_0x10000077,
|
||||
kMessage_0x10000078,
|
||||
kMessage_0x10000079,
|
||||
kMessage_0x1000007a,
|
||||
kMessage_0x1000007b,
|
||||
kMessage_0x1000007c,
|
||||
kMessage_0x1000007d,
|
||||
kMessage_0x1000007e,
|
||||
kWriteToChatLog, // 0x1000007F, wparam = UIPacket::kWriteToChatLog*
|
||||
kWriteToChatLogWithSender, // 0x10000080, wparam = UIPacket::kWriteToChatLogWithSender*
|
||||
kAllyOrGuildMessage, // 0x10000081, wparam = UIPacket::kAllyOrGuildMessage*
|
||||
kPlayerChatMessage, // 0x10000082, wparam = UIPacket::kPlayerChatMessage*
|
||||
kMessage_0x10000083,
|
||||
kFloatingWindowMoved, // 0x10000084, wparam = frame_id
|
||||
kMessage_0x10000085,
|
||||
kMessage_0x10000086,
|
||||
kMessage_0x10000087,
|
||||
kMessage_0x10000088,
|
||||
kMessage_0x10000089,
|
||||
kMessage_0x1000008a,
|
||||
kFriendUpdated, // 0x1000008B, wparam = { GW::Friend*, ... }
|
||||
kMapLoaded, // 0x1000008C
|
||||
kMessage_0x1000008d,
|
||||
kMessage_0x1000008e,
|
||||
kMessage_0x1000008f,
|
||||
kMessage_0x10000090,
|
||||
kMessage_0x10000091,
|
||||
kOpenWhisper, // 0x10000092, wparam = wchar* name
|
||||
kMessage_0x10000093,
|
||||
kMessage_0x10000094,
|
||||
kMessage_0x10000095,
|
||||
kMessage_0x10000096,
|
||||
kMessage_0x10000097,
|
||||
kLoadMapContext, // 0x10000098, wparam = UIPacket::kLoadMapContext
|
||||
kMessage_0x10000099,
|
||||
kMessage_0x1000009a,
|
||||
kMessage_0x1000009b,
|
||||
kDialogueMessageUpdated, // 0x1000009c
|
||||
kLogout, // 0x1000009D, wparam = { bool unknown, bool character_select }
|
||||
kCompassDraw, // 0x1000009E, wparam = UIPacket::kCompassDraw*
|
||||
kMessage_0x1000009f,
|
||||
kMessage_0x100000a0,
|
||||
kMessage_0x100000a1,
|
||||
kOnScreenMessage, // 0x100000A2, wparam = wchar_** encoded_string
|
||||
kDialogButton, // 0x100000A3, wparam = DialogButtonInfo*
|
||||
kMessage_0x100000a4,
|
||||
kMessage_0x100000a5,
|
||||
kDialogBody, // 0x100000A6, wparam = DialogBodyInfo*
|
||||
kMessage_0x100000a7,
|
||||
kMessage_0x100000a8,
|
||||
kMessage_0x100000a9,
|
||||
kMessage_0x100000aa,
|
||||
kMessage_0x100000ab,
|
||||
kMessage_0x100000ac,
|
||||
kMessage_0x100000ad,
|
||||
kMessage_0x100000ae,
|
||||
kMessage_0x100000af,
|
||||
kMessage_0x100000b0,
|
||||
kMessage_0x100000b1,
|
||||
kMessage_0x100000b2,
|
||||
kTargetNPCPartyMember, // 0x100000B3, wparam = { uint32_t unk, uint32_t agent_id }
|
||||
kTargetPlayerPartyMember, // 0x100000B4, wparam = { uint32_t unk, uint32_t player_number }
|
||||
kVendorWindow, // 0x100000B5, wparam = UIPacket::kVendorWindow
|
||||
kMessage_0x100000b6,
|
||||
kMessage_0x100000b7,
|
||||
kMessage_0x100000b8,
|
||||
kVendorItems, // 0x100000B9, wparam = UIPacket::kVendorItems
|
||||
kMessage_0x100000ba,
|
||||
kVendorTransComplete, // 0x100000BB, wparam = *TransactionType
|
||||
kMessage_0x100000bc,
|
||||
kVendorQuote, // 0x100000BD, wparam = UIPacket::kVendorQuote
|
||||
kMessage_0x100000be,
|
||||
kMessage_0x100000bf,
|
||||
kMessage_0x100000c0,
|
||||
kMessage_0x100000c1,
|
||||
kStartMapLoad, // 0x100000C2, wparam = { uint32_t map_id, ...}
|
||||
kMessage_0x100000c3,
|
||||
kMessage_0x100000c4,
|
||||
kMessage_0x100000c5,
|
||||
kMessage_0x100000c6,
|
||||
kWorldMapUpdated, // 0x100000C7, Triggered when an area in the world map has been discovered/updated
|
||||
kMessage_0x100000c8,
|
||||
kMessage_0x100000c9,
|
||||
kMessage_0x100000ca,
|
||||
kMessage_0x100000cb,
|
||||
kMessage_0x100000cc,
|
||||
kMessage_0x100000cd,
|
||||
kMessage_0x100000ce,
|
||||
kMessage_0x100000cf,
|
||||
kMessage_0x100000d0,
|
||||
kMessage_0x100000d1,
|
||||
kMessage_0x100000d2,
|
||||
kMessage_0x100000d3,
|
||||
kMessage_0x100000d4,
|
||||
kMessage_0x100000d5,
|
||||
kMessage_0x100000d6,
|
||||
kMessage_0x100000d7,
|
||||
kMessage_0x100000d8,
|
||||
kMessage_0x100000d9,
|
||||
kGuildMemberUpdated, // 0x100000DA, wparam = { GuildPlayer::name_ptr }
|
||||
kMessage_0x100000db,
|
||||
kMessage_0x100000dc,
|
||||
kMessage_0x100000dd,
|
||||
kMessage_0x100000de,
|
||||
kMessage_0x100000df,
|
||||
kMessage_0x100000e0,
|
||||
kShowHint, // 0x100000E1, wparam = { uint32_t icon_type, wchar_t* message_enc }
|
||||
kMessage_0x100000e2,
|
||||
kMessage_0x100000e3,
|
||||
kMessage_0x100000e4,
|
||||
kMessage_0x100000e5,
|
||||
kMessage_0x100000e6,
|
||||
kMessage_0x100000e7,
|
||||
kMessage_0x100000e8,
|
||||
kWeaponSetSwapComplete, // 0x100000E9, wparam = UIPacket::kWeaponSwap*
|
||||
kWeaponSetSwapCancel, // 0x100000EA
|
||||
kWeaponSetUpdated, // 0x100000EB
|
||||
kUpdateGoldCharacter, // 0x100000EC, wparam = { uint32_t unk, uint32_t gold_character }
|
||||
kUpdateGoldStorage, // 0x100000ED, wparam = { uint32_t unk, uint32_t gold_storage }
|
||||
kInventorySlotUpdated, // 0x100000EE, Triggered when an item is moved into a slot
|
||||
kEquipmentSlotUpdated, // 0x100000EF, Triggered when an item is moved into a slot
|
||||
kMessage_0x100000f0,
|
||||
kInventorySlotCleared, // 0x100000F1, Triggered when an item has been removed from a slot
|
||||
kEquipmentSlotCleared, // 0x100000F2, Triggered when an item has been removed from a slot
|
||||
kMessage_0x100000f3,
|
||||
kMessage_0x100000f4,
|
||||
kMessage_0x100000f5,
|
||||
kMessage_0x100000f6,
|
||||
kMessage_0x100000f7,
|
||||
kMessage_0x100000f8,
|
||||
kMessage_0x100000f9,
|
||||
kPvPWindowContent, // 0x100000FA
|
||||
kMessage_0x100000fb,
|
||||
kMessage_0x100000fc,
|
||||
kMessage_0x100000fd,
|
||||
kMessage_0x100000fe,
|
||||
kMessage_0x100000ff,
|
||||
kMessage_0x10000100,
|
||||
kMessage_0x10000101,
|
||||
kPreStartSalvage, // 0x10000102, { uint32_t item_id, uint32_t kit_id }
|
||||
kTomeSkillSelection, // 0x10000103, wparam = UIPacket::kTomeSkillSelection*
|
||||
kMessage_0x10000104,
|
||||
kTradePlayerUpdated, // 0x10000105, wparam = GW::TraderPlayer*
|
||||
kItemUpdated, // 0x10000106, wparam = UIPacket::kItemUpdated*
|
||||
kMessage_0x10000107,
|
||||
kMessage_0x10000108,
|
||||
kMessage_0x10000109,
|
||||
kMessage_0x1000010a,
|
||||
kMessage_0x1000010b,
|
||||
kMessage_0x1000010c,
|
||||
kMessage_0x1000010d,
|
||||
kMessage_0x1000010e,
|
||||
kMessage_0x1000010f,
|
||||
kMessage_0x10000110,
|
||||
kMapChange, // 0x10000111, wparam = map id
|
||||
kMessage_0x10000112,
|
||||
kMessage_0x10000113,
|
||||
kMessage_0x10000114,
|
||||
kCalledTargetChange, // 0x10000115, wparam = { player_number, target_id }
|
||||
kMessage_0x10000116,
|
||||
kMessage_0x10000117,
|
||||
kMessage_0x10000118,
|
||||
kErrorMessage, // 0x10000119, wparam = { int error_index, wchar_t* error_encoded_string }
|
||||
kPartyHardModeChanged, // 0x1000011A, wparam = { int is_hard_mode }
|
||||
kPartyAddHenchman, // 0x1000011B
|
||||
kPartyRemoveHenchman, // 0x1000011C
|
||||
kMessage_0x1000011d,
|
||||
kPartyAddHero, // 0x1000011E
|
||||
kPartyRemoveHero, // 0x1000011F
|
||||
kMessage_0x10000120,
|
||||
kMessage_0x10000121,
|
||||
kMessage_0x10000122,
|
||||
kMessage_0x10000123,
|
||||
kPartyAddPlayer, // 0x10000124
|
||||
kMessage_0x10000125,
|
||||
kPartyRemovePlayer, // 0x10000126
|
||||
kMessage_0x10000127,
|
||||
kMessage_0x10000128,
|
||||
kMessage_0x10000129,
|
||||
kDisableEnterMissionBtn, // 0x1000012A, wparam = boolean (1 = disabled, 0 = enabled)
|
||||
kMessage_0x1000012b,
|
||||
kMessage_0x1000012c,
|
||||
kShowCancelEnterMissionBtn, // 0x1000012D
|
||||
kMessage_0x1000012e,
|
||||
kPartyDefeated, // 0x1000012F
|
||||
kMessage_0x10000130,
|
||||
kMessage_0x10000131,
|
||||
kMessage_0x10000132,
|
||||
kPartySearchCreated, // 0x10000133, wparam = GW::PartySearch*
|
||||
kPartySearchIdChanged, // 0x10000134, wparam = uint32_t* party_search_id
|
||||
kPartySearchRemoved, // 0x10000135, wparam = uint32_t* party_search_id
|
||||
kPartySearchUpdated, // 0x10000136, wparam = GW::PartySearch*
|
||||
kPartySearchInviteReceived, // 0x10000137, wparam = UIPacket::kPartySearchInviteReceived*
|
||||
kMessage_0x10000138,
|
||||
kPartySearchInviteSent, // 0x10000139
|
||||
kPartyShowConfirmDialog, // 0x1000013A, wparam = UIPacket::kPartyShowConfirmDialog
|
||||
kMessage_0x1000013b,
|
||||
kMessage_0x1000013c,
|
||||
kMessage_0x1000013d,
|
||||
kMessage_0x1000013e,
|
||||
kMessage_0x1000013f,
|
||||
kPreferenceEnumChanged, // 0x10000140, wparam = UiPacket::kPreferenceEnumChanged
|
||||
kPreferenceFlagChanged, // 0x10000141, wparam = UiPacket::kPreferenceFlagChanged
|
||||
kPreferenceValueChanged, // 0x10000142, wparam = UiPacket::kPreferenceValueChanged
|
||||
kUIPositionChanged, // 0x10000143, wparam = UIPacket::kUIPositionChanged
|
||||
kPreBuildLoginScene, // 0x10000144, Called with no args right before login scene is drawn
|
||||
kMessage_0x10000145,
|
||||
kMessage_0x10000146,
|
||||
kMessage_0x10000147,
|
||||
kMessage_0x10000148,
|
||||
kMessage_0x10000149,
|
||||
kMessage_0x1000014a,
|
||||
kMessage_0x1000014b,
|
||||
kMessage_0x1000014c,
|
||||
kMessage_0x1000014d,
|
||||
kQuestAdded, // 0x1000014E, wparam = { quest_id, ... }
|
||||
kQuestDetailsChanged, // 0x1000014F, wparam = { quest_id, ... }
|
||||
kQuestRemoved, // 0x10000150, wparam = { quest_id, ... }
|
||||
kClientActiveQuestChanged, // 0x10000151, wparam = { quest_id, ... }. Triggered when the game requests the current quest to change
|
||||
kMessage_0x10000152,
|
||||
kServerActiveQuestChanged, // 0x10000153, wparam = UIPacket::kServerActiveQuestChanged*. Triggered when the server requests the current quest to change
|
||||
kUnknownQuestRelated, // 0x10000154
|
||||
kMessage_0x10000155,
|
||||
kDungeonComplete, // 0x10000156
|
||||
kMissionComplete, // 0x10000157
|
||||
kMessage_0x10000158,
|
||||
kVanquishComplete, // 0x10000159
|
||||
kObjectiveAdd, // 0x1000015A, wparam = UIPacket::kObjectiveAdd*
|
||||
kObjectiveComplete, // 0x1000015B, wparam = UIPacket::kObjectiveComplete*
|
||||
kObjectiveUpdated, // 0x1000015C, wparam = UIPacket::kObjectiveUpdated*
|
||||
kMessage_0x1000015d,
|
||||
kMessage_0x1000015e,
|
||||
kMessage_0x1000015f,
|
||||
kMessage_0x10000160,
|
||||
kMessage_0x10000161,
|
||||
kMessage_0x10000162,
|
||||
kMessage_0x10000163,
|
||||
kMessage_0x10000164,
|
||||
kTradeSessionStart, // 0x10000165, wparam = { trade_state, player_number }
|
||||
kMessage_0x10000166,
|
||||
kMessage_0x10000167,
|
||||
kMessage_0x10000168,
|
||||
kMessage_0x10000169,
|
||||
kMessage_0x1000016a,
|
||||
kTradeSessionUpdated, // 0x1000016b, no args
|
||||
kMessage_0x1000016c,
|
||||
kMessage_0x1000016d,
|
||||
kMessage_0x1000016e,
|
||||
kMessage_0x1000016f,
|
||||
kMessage_0x10000170,
|
||||
kMessage_0x10000171,
|
||||
kMessage_0x10000172,
|
||||
kMessage_0x10000173,
|
||||
kMessage_0x10000174,
|
||||
kCheckUIState, // 0x10000175
|
||||
kMessage_0x10000176,
|
||||
kMessage_0x10000177,
|
||||
kMessage_0x10000178,
|
||||
kMessage_0x10000178_1, // added to GW 2026-02-26
|
||||
kMessage_0x10000178_2, // added to GW 2026-02-26
|
||||
kMessage_0x10000178_3, // added to GW 2026-02-26
|
||||
kDestroyUIPositionOverlay, // 0x10000179
|
||||
kEnableUIPositionOverlay, // 0x1000017a, wparam = uint32_t enable
|
||||
kMessage_0x1000017b,
|
||||
kGuildHall, // 0x1000017C, wparam = gh key (uint32_t[4])
|
||||
kMessage_0x1000017d,
|
||||
kLeaveGuildHall, // 0x1000017E
|
||||
kTravel, // 0x1000017F
|
||||
kOpenWikiUrl, // 0x10000180, wparam = char* url
|
||||
kMessage_0x10000181,
|
||||
kMessage_0x10000182,
|
||||
kSetPreGameContext_Value0, // wparam = uint32_t value
|
||||
kMessage_0x10000184,
|
||||
kGetPreGameContext_Value0, // lparam = *uint32_t value_out
|
||||
kSetPreGameContext_Value1, // wparam = uint32_t value , added to GW 2026-02-06
|
||||
kGetPreGameContext_Value1, // lparam = *uint32_t value_out, added to GW 2026-02-06
|
||||
kMessage_0x10000186,
|
||||
kMessage_0x10000187,
|
||||
kMessage_0x10000188,
|
||||
kMessage_0x10000189,
|
||||
kMessage_0x1000018a,
|
||||
kMessage_0x1000018b,
|
||||
kMessage_0x1000018c,
|
||||
kMessage_0x1000018d,
|
||||
kAppendMessageToChat, // 0x1000018E, wparam = wchar_t* message
|
||||
kMessage_0x1000018f,
|
||||
kMessage_0x10000190,
|
||||
kMessage_0x10000191,
|
||||
kMessage_0x10000192,
|
||||
kMessage_0x10000193,
|
||||
kMessage_0x10000194,
|
||||
kMessage_0x10000195,
|
||||
kMessage_0x10000196,
|
||||
kMessage_0x10000197,
|
||||
kMessage_0x10000198,
|
||||
kMessage_0x10000199,
|
||||
kMessage_0x1000019a,
|
||||
kMessage_0x1000019b,
|
||||
kHideHeroPanel, // 0x1000019C, wparam = hero_id
|
||||
kShowHeroPanel, // 0x1000019D, wparam = hero_id
|
||||
kMessage_0x1000019e,
|
||||
kMessage_0x1000019f,
|
||||
kMessage_0x100001a0,
|
||||
kGetInventoryAgentId, // 0x100001A1, wparam = 0, lparam = uint32_t* agent_id_out. Used to fetch which agent is selected
|
||||
kEquipItem, // 0x100001A2, wparam = { item_id, agent_id }
|
||||
kMoveItem, // 0x100001A3, wparam = { item_id, to_bag, to_slot, bool prompt }
|
||||
kMessage_0x100001a4,
|
||||
kMessage_0x100001a5,
|
||||
kInitiateTrade, // 0x100001A6
|
||||
kMessage_0x100001a7,
|
||||
kMessage_0x100001a8,
|
||||
kMessage_0x100001a9,
|
||||
kMessage_0x100001aa,
|
||||
kMessage_0x100001ab,
|
||||
kMessage_0x100001ac,
|
||||
kMessage_0x100001ad,
|
||||
kMessage_0x100001ae,
|
||||
kMessage_0x100001af,
|
||||
kMessage_0x100001b0,
|
||||
kMessage_0x100001b1,
|
||||
kMessage_0x100001b2,
|
||||
kMessage_0x100001b3,
|
||||
kMessage_0x100001b4,
|
||||
kMessage_0x100001b5,
|
||||
kInventoryAgentChanged, // 0x100001B6, Triggered when inventory needs updating due to agent change; no args
|
||||
kMessage_0x100001b7,
|
||||
kMessage_0x100001b8,
|
||||
kMessage_0x100001b9,
|
||||
kMessage_0x100001ba,
|
||||
kMessage_0x100001bb,
|
||||
kMessage_0x100001bc,
|
||||
kMessage_0x100001bd,
|
||||
kPromptSaveTemplate, // 0x100001be
|
||||
kOpenTemplate, // 0x100001Bf, wparam = GW::UI::ChatTemplate*
|
||||
|
||||
// GWCA Client to Server commands. Only added the ones that are used for hooks, everything else goes straight into GW
|
||||
|
||||
kSendLoadSkillTemplate = 0x30000000 | 0x3, // wparam = SkillbarMgr::SkillTemplate*
|
||||
kSendPingWeaponSet = 0x30000000 | 0x4, // wparam = UIPacket::kSendPingWeaponSet*
|
||||
kSendMoveItem = 0x30000000 | 0x5, // wparam = UIPacket::kSendMoveItem*
|
||||
kSendMerchantRequestQuote = 0x30000000 | 0x6, // wparam = UIPacket::kSendMerchantRequestQuote*
|
||||
kSendMerchantTransactItem = 0x30000000 | 0x7, // wparam = UIPacket::kSendMerchantTransactItem*
|
||||
kSendUseItem = 0x30000000 | 0x8, // wparam = UIPacket::kSendUseItem*
|
||||
kSendSetActiveQuest = 0x30000000 | 0x9, // wparam = uint32_t quest_id
|
||||
kSendAbandonQuest = 0x30000000 | 0xA, // wparam = uint32_t quest_id
|
||||
kSendChangeTarget = 0x30000000 | 0xB, // wparam = UIPacket::kSendChangeTarget* // e.g. tell the gw client to focus on a different target
|
||||
kSendCallTarget = 0x30000000 | 0x13, // wparam = { uint32_t call_type, uint32_t agent_id } // also used to broadcast morale, death penalty, "I'm following X", etc
|
||||
kSendDialog = 0x30000000 | 0x16, // wparam = dialog_id // internal use
|
||||
|
||||
|
||||
kStartWhisper = 0x30000000 | 0x17, // wparam = UIPacket::kStartWhisper*
|
||||
kGetSenderColor = 0x30000000 | 0x18, // wparam = UIPacket::kGetColor* // Get chat sender color depending on channel, output object passed by reference
|
||||
kGetMessageColor = 0x30000000 | 0x19, // wparam = UIPacket::kGetColor* // Get chat message color depending on channel, output object passed by reference
|
||||
kSendChatMessage = 0x30000000 | 0x1B, // wparam = UIPacket::kSendChatMessage*
|
||||
kLogChatMessage = 0x30000000 | 0x1D, // wparam = UIPacket::kLogChatMessage*. Triggered when a message wants to be added to the persistent chat log.
|
||||
kRecvWhisper = 0x30000000 | 0x1E, // wparam = UIPacket::kRecvWhisper*
|
||||
kPrintChatMessage = 0x30000000 | 0x1F, // wparam = UIPacket::kPrintChatMessage*. Triggered when a message wants to be added to the in-game chat window.
|
||||
kSendWorldAction = 0x30000000 | 0x20, // wparam = UIPacket::kSendWorldAction*
|
||||
kSetRendererValue = 0x30000000 | 0x21, // wparam = UIPacket::kSetRendererValue
|
||||
kIdentifyItem = 0x30000000 | 0x22, // wparam = UIPacket::kUseKitOnItem
|
||||
kSalvageItem = 0x30000000 | 0x23 // wparam = UIPacket::kUseKitOnItem
|
||||
};
|
||||
|
||||
static_assert(GW::UI::UIMessage::kOpenTemplate == (GW::UI::UIMessage)0x100001c4);
|
||||
|
||||
namespace UIPacket {
|
||||
struct kDialogueMessage {
|
||||
uint32_t agent_id;
|
||||
wchar_t* sender;
|
||||
wchar_t* message;
|
||||
uint32_t duration;
|
||||
uint32_t is_dialogue_1_or_2;
|
||||
};
|
||||
struct kErrorMessage {
|
||||
uint32_t error_id;
|
||||
wchar_t* message;
|
||||
};
|
||||
struct kAgentSkillPacket {
|
||||
uint32_t agent_id;
|
||||
GW::Constants::SkillID skill_id;
|
||||
};
|
||||
struct kLoadMapContext {
|
||||
const wchar_t* file_name;
|
||||
Constants::MapID map_id;
|
||||
Constants::InstanceType map_type;
|
||||
Vec2f spawn_point;
|
||||
uint32_t h0014;
|
||||
uint32_t h0018;
|
||||
bool* success;
|
||||
};
|
||||
static_assert(sizeof(kLoadMapContext) == 0x20);
|
||||
struct kMouseCoordsClick {
|
||||
float offset_x;
|
||||
float offset_y;
|
||||
uint32_t h0008;
|
||||
uint32_t h000c;
|
||||
uint32_t* h0010;
|
||||
uint32_t h0014;
|
||||
};
|
||||
struct kUseKitOnItem {
|
||||
uint32_t item_id;
|
||||
uint32_t kit_id;
|
||||
};
|
||||
struct kShowXunlaiChest {
|
||||
uint32_t h0000 = 0;
|
||||
bool storage_pane_unlocked = true;
|
||||
bool anniversary_pane_unlocked = true;
|
||||
};
|
||||
struct kMoveItem {
|
||||
uint32_t item_id;
|
||||
uint32_t to_bag_index;
|
||||
uint32_t to_slot;
|
||||
uint32_t prompt;
|
||||
};
|
||||
struct kResize {
|
||||
uint32_t h0000 = 0xffffffff;
|
||||
float content_width;
|
||||
float content_height;
|
||||
float h000c = 0;
|
||||
float h0010 = 0;
|
||||
float content_width2;
|
||||
float content_height2;
|
||||
float margin_x;
|
||||
float margin_y;
|
||||
// ...
|
||||
};
|
||||
struct kTomeSkillSelection {
|
||||
uint32_t item_id;
|
||||
uint32_t h0004;
|
||||
uint32_t h0008;
|
||||
};
|
||||
struct kMeasureContent {
|
||||
float max_width; // Maximum width constraint
|
||||
float max_height; // Maximum height constraint
|
||||
float* size_output; // Pointer to output buffer for calculated size
|
||||
uint32_t flags; // Layout flags (similar to the 0x100 flag we saw)
|
||||
};
|
||||
struct kSetLayout {
|
||||
float field_0x0;
|
||||
float field_0x4;
|
||||
float field_0x8;
|
||||
float field_0xc;
|
||||
float available_width;
|
||||
float available_height;
|
||||
};
|
||||
struct kSetAgentProfession {
|
||||
AgentID agent_id;
|
||||
uint32_t primary;
|
||||
uint32_t secondary;
|
||||
};
|
||||
struct kWeaponSwap {
|
||||
uint32_t weapon_bar_frame_id;
|
||||
uint32_t weapon_set_id;
|
||||
};
|
||||
struct kWeaponSetChanged {
|
||||
uint32_t h0000;
|
||||
uint32_t h0004;
|
||||
uint32_t h0008;
|
||||
uint32_t h000c;
|
||||
};
|
||||
struct kChangeTarget {
|
||||
uint32_t evaluated_target_id;
|
||||
bool has_evaluated_target_changed;
|
||||
uint32_t auto_target_id;
|
||||
bool has_auto_target_changed;
|
||||
uint32_t manual_target_id;
|
||||
bool has_manual_target_changed;
|
||||
};
|
||||
struct kSendLoadSkillTemplate {
|
||||
uint32_t agent_id;
|
||||
SkillbarMgr::SkillTemplate* skill_template;
|
||||
};
|
||||
struct kVendorWindow {
|
||||
Merchant::TransactionType transaction_type;
|
||||
uint32_t unk;
|
||||
uint32_t merchant_agent_id;
|
||||
uint32_t is_pending;
|
||||
};
|
||||
struct kVendorQuote {
|
||||
uint32_t item_id;
|
||||
uint32_t price;
|
||||
};
|
||||
struct kVendorItems {
|
||||
Merchant::TransactionType transaction_type;
|
||||
uint32_t item_ids_count;
|
||||
uint32_t* item_ids_buffer1; // world->merchant_items.buffer
|
||||
uint32_t* item_ids_buffer2; // world->merchant_items2.buffer
|
||||
};
|
||||
struct kSetRendererValue {
|
||||
uint32_t renderer_mode; // 0 for window, 2 for full screen
|
||||
uint32_t metric_id; // TODO: Enum this!
|
||||
uint32_t value;
|
||||
};
|
||||
struct kEffectAdd {
|
||||
uint32_t agent_id;
|
||||
Effect* effect;
|
||||
};
|
||||
struct kAgentSpeechBubble {
|
||||
uint32_t agent_id;
|
||||
wchar_t* message;
|
||||
uint32_t h0008;
|
||||
uint32_t h000c;
|
||||
};
|
||||
struct kAgentSkillStartedCast {
|
||||
uint32_t agent_id;
|
||||
Constants::SkillID skill_id;
|
||||
float duration;
|
||||
uint32_t h000c;
|
||||
};
|
||||
struct kPreStartSalvage {
|
||||
uint32_t item_id;
|
||||
uint32_t kit_id;
|
||||
};
|
||||
struct kServerActiveQuestChanged {
|
||||
GW::Constants::QuestID quest_id;
|
||||
GW::GamePos marker;
|
||||
uint32_t h0024;
|
||||
GW::Constants::MapID map_id;
|
||||
uint32_t log_state;
|
||||
};
|
||||
struct kPrintChatMessage {
|
||||
GW::Chat::Channel channel;
|
||||
wchar_t* message;
|
||||
FILETIME timestamp;
|
||||
uint32_t is_reprint;
|
||||
};
|
||||
struct kPartyShowConfirmDialog {
|
||||
uint32_t ui_message_to_send_to_party_frame;
|
||||
uint32_t prompt_identitifier;
|
||||
wchar_t* prompt_enc_str;
|
||||
};
|
||||
struct kUIPositionChanged {
|
||||
uint32_t window_id;
|
||||
UI::WindowPosition* position;
|
||||
};
|
||||
struct kPreferenceFlagChanged {
|
||||
UI::FlagPreference preference_id;
|
||||
uint32_t new_value;
|
||||
};
|
||||
struct kPreferenceValueChanged {
|
||||
UI::NumberPreference preference_id;
|
||||
uint32_t new_value;
|
||||
};
|
||||
struct kPreferenceEnumChanged {
|
||||
UI::EnumPreference preference_id;
|
||||
uint32_t enum_index;
|
||||
};
|
||||
struct kPartySearchInvite {
|
||||
uint32_t source_party_search_id;
|
||||
uint32_t dest_party_search_id;
|
||||
};
|
||||
struct kPostProcessingEffect {
|
||||
uint32_t tint;
|
||||
float amount;
|
||||
};
|
||||
struct kLogout {
|
||||
uint32_t unknown;
|
||||
uint32_t character_select;
|
||||
};
|
||||
static_assert(sizeof(kLogout) == 0x8);
|
||||
|
||||
struct kKeyAction {
|
||||
uint32_t gw_key;
|
||||
uint32_t modifiers = 0;
|
||||
uint32_t state_flags = 0; // shift held = 0x4, ctrl = 0x2, alt = 0x1
|
||||
};
|
||||
struct kMouseClick {
|
||||
uint32_t mouse_button; // 0x0 = left, 0x1 = middle, 0x2 = right
|
||||
uint32_t is_doubleclick;
|
||||
uint32_t unknown_type_screen_pos;
|
||||
uint32_t h000c;
|
||||
uint32_t h0010;
|
||||
};
|
||||
enum ActionState : uint32_t {
|
||||
MouseDown = 0x6,
|
||||
MouseUp = 0x7,
|
||||
MouseClick = 0x8,
|
||||
MouseDoubleClick = 0x9,
|
||||
DragRelease = 0xb,
|
||||
KeyDown = 0xe
|
||||
};
|
||||
struct kMouseAction {
|
||||
uint32_t frame_id;
|
||||
uint32_t child_offset_id;
|
||||
ActionState current_state;
|
||||
void* wparam = 0;
|
||||
void* lparam = 0;
|
||||
};
|
||||
struct kWriteToChatLog {
|
||||
GW::Chat::Channel channel;
|
||||
wchar_t* message;
|
||||
GW::Chat::Channel channel_dupe;
|
||||
};
|
||||
struct kPlayerChatMessage {
|
||||
GW::Chat::Channel channel;
|
||||
wchar_t* message;
|
||||
uint32_t player_number;
|
||||
};
|
||||
|
||||
struct kInteractAgent {
|
||||
uint32_t agent_id;
|
||||
bool call_target;
|
||||
};
|
||||
|
||||
struct kSendChangeTarget {
|
||||
uint32_t target_id;
|
||||
uint32_t auto_target_id;
|
||||
};
|
||||
|
||||
struct kSendCallTarget {
|
||||
CallTargetType call_type;
|
||||
uint32_t agent_id;
|
||||
};
|
||||
|
||||
struct kGetColor {
|
||||
Chat::Color* color;
|
||||
GW::Chat::Channel channel;
|
||||
};
|
||||
|
||||
struct kWriteToChatLogWithSender {
|
||||
uint32_t channel;
|
||||
wchar_t* message;
|
||||
wchar_t* sender_enc;
|
||||
};
|
||||
|
||||
struct kSendPingWeaponSet {
|
||||
uint32_t agent_id;
|
||||
uint32_t weapon_item_id;
|
||||
uint32_t offhand_item_id;
|
||||
};
|
||||
struct kSendMoveItem {
|
||||
uint32_t item_id;
|
||||
uint32_t quantity;
|
||||
uint32_t bag_index;
|
||||
uint32_t slot;
|
||||
};
|
||||
struct kSendMerchantRequestQuote {
|
||||
Merchant::TransactionType type;
|
||||
uint32_t item_id;
|
||||
};
|
||||
struct kSendMerchantTransactItem {
|
||||
Merchant::TransactionType type;
|
||||
uint32_t h0004;
|
||||
Merchant::QuoteInfo give;
|
||||
uint32_t gold_recv;
|
||||
Merchant::QuoteInfo recv;
|
||||
};
|
||||
struct kSendUseItem {
|
||||
uint32_t item_id;
|
||||
uint16_t quantity; // Unused, but would be cool
|
||||
};
|
||||
struct kSendChatMessage {
|
||||
wchar_t* message;
|
||||
uint32_t agent_id;
|
||||
};
|
||||
struct kLogChatMessage {
|
||||
wchar_t* message;
|
||||
GW::Chat::Channel channel;
|
||||
};
|
||||
struct kRecvWhisper {
|
||||
uint32_t transaction_id;
|
||||
wchar_t* from;
|
||||
wchar_t* message;
|
||||
};
|
||||
struct kStartWhisper {
|
||||
wchar_t* player_name;
|
||||
};
|
||||
struct kCompassDraw {
|
||||
uint32_t player_number;
|
||||
uint32_t session_id;
|
||||
uint32_t number_of_points;
|
||||
CompassPoint* points;
|
||||
};
|
||||
struct kObjectiveAdd {
|
||||
uint32_t objective_id;
|
||||
wchar_t* name;
|
||||
uint32_t type;
|
||||
};
|
||||
struct kObjectiveComplete {
|
||||
uint32_t objective_id;
|
||||
};
|
||||
struct kObjectiveUpdated {
|
||||
uint32_t objective_id;
|
||||
};
|
||||
// Straight passthru of GW::Packets::StoC::ItemGeneral
|
||||
struct kItemUpdated {
|
||||
uint32_t item_id;
|
||||
uint32_t model_file_id;
|
||||
uint32_t type;
|
||||
uint32_t unk1;
|
||||
uint32_t extra_id; // Dye color
|
||||
uint32_t materials;
|
||||
uint32_t unk2;
|
||||
uint32_t interaction; // Flags
|
||||
uint32_t price;
|
||||
uint32_t model_id;
|
||||
uint32_t quantity;
|
||||
wchar_t* enc_name;
|
||||
uint32_t mod_struct_size;
|
||||
uint32_t* mod_struct;
|
||||
};
|
||||
struct kInventorySlotUpdated {
|
||||
uint32_t unk;
|
||||
uint32_t item_id;
|
||||
uint32_t bag_index;
|
||||
uint32_t slot_id;
|
||||
};
|
||||
struct kSendWorldAction {
|
||||
WorldActionId action_id;
|
||||
GW::AgentID agent_id;
|
||||
bool suppress_call_target; // 1 to block "I'm targetting X", but will also only trigger if the key thing is down
|
||||
};
|
||||
struct kAllyOrGuildMessage {
|
||||
GW::Chat::Channel channel;
|
||||
wchar_t* message;
|
||||
wchar_t* sender;
|
||||
wchar_t* guild_tag;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
#include <GWCA/Utilities/Export.h>
|
||||
|
||||
namespace GW {
|
||||
struct AccountContext;
|
||||
GWCA_API AccountContext* GetAccountContext();
|
||||
|
||||
struct AccountUnlockedCount {
|
||||
uint32_t id;
|
||||
uint32_t unk1;
|
||||
uint32_t unk2;
|
||||
};
|
||||
|
||||
struct AccountUnlockedItemInfo {
|
||||
uint32_t name_id;
|
||||
uint32_t mod_struct_index; // Used to find mod struct in unlocked_pvp_items_mod_structs...
|
||||
uint32_t mod_struct_size;
|
||||
};
|
||||
|
||||
struct AccountContext {
|
||||
/* +h0000 */ Array<AccountUnlockedCount> account_unlocked_counts; // e.g. number of unlocked storage panes
|
||||
/* +h0010 */ uint8_t h0010[0xA4];
|
||||
/* +h00b4 */ Array<uint32_t> unlocked_pvp_heros; // Unused, hero battles is no more :(
|
||||
/* +h00c4 */ Array<uint32_t> h00c4;// If an item is unlocked, the mod struct is stored here. Use unlocked_pvp_items_info to find the index. Idk why, chaos reigns I guess
|
||||
/* +h00e4 */ Array<AccountUnlockedItemInfo> unlocked_pvp_item_info; // If an item is unlocked, the details are stored here
|
||||
/* +h00f4 */ Array<uint32_t> unlocked_pvp_items; // Bitwise array of which pvp items are unlocked
|
||||
/* +h0104 */ uint8_t h0104[0x30]; // Some arrays, some linked lists, meh
|
||||
/* +h0124 */ Array<uint32_t> unlocked_account_skills; // List of skills unlocked (but not learnt) for this account, i.e. skills that heros can use, tomes can unlock
|
||||
/* +h0134 */ uint32_t account_flags;
|
||||
};
|
||||
static_assert(sizeof(AccountContext) == 0x138);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
#include <GWCA/Utilities/Export.h>
|
||||
|
||||
namespace GW {
|
||||
struct AgentContext;
|
||||
GWCA_API AgentContext* GetAgentContext();
|
||||
|
||||
struct AgentMovement;
|
||||
struct Agent;
|
||||
|
||||
struct AgentSummaryInfo {
|
||||
struct AgentSummaryInfoSub {
|
||||
/* +h0000 */ uint32_t h0000;
|
||||
/* +h0004 */ uint32_t h0004;
|
||||
/* +h0008 */ uint32_t gadget_id;
|
||||
/* +h000C */ uint32_t h000C;
|
||||
/* +h0010 */ wchar_t * gadget_name_enc;
|
||||
/* +h0014 */ uint32_t h0014;
|
||||
/* +h0018 */ uint32_t composite_agent_id; // 0x30000000 | player_id, 0x20000000 | npc_id etc
|
||||
};
|
||||
|
||||
uint32_t h0000;
|
||||
uint32_t h0004;
|
||||
AgentSummaryInfoSub* extra_info_sub;
|
||||
};
|
||||
|
||||
struct AgentContext {
|
||||
/* +h0000 */ Array<void *> h0000;
|
||||
/* +h0010 */ uint32_t h0010[5];
|
||||
/* +h0024 */ uint32_t h0024; // function
|
||||
/* +h0028 */ uint32_t h0028[2];
|
||||
/* +h0030 */ uint32_t h0030; // function
|
||||
/* +h0034 */ uint32_t h0034[2];
|
||||
/* +h003C */ uint32_t h003C; // function
|
||||
/* +h0040 */ uint32_t h0040[2];
|
||||
/* +h0048 */ uint32_t h0048; // function
|
||||
/* +h004C */ uint32_t h004C[2];
|
||||
/* +h0054 */ uint32_t h0054; // function
|
||||
/* +h0058 */ uint32_t h0058[11];
|
||||
/* +h0084 */ Array<void *> h0084;
|
||||
/* +h0094 */ uint32_t h0094; // this field and the next array are link together in a structure.
|
||||
/* +h0098 */ Array<AgentSummaryInfo> agent_summary_info; // elements are of size 12. {ptr, func, ptr}
|
||||
/* +h00A8 */ Array<void *> h00A8;
|
||||
/* +h00B8 */ Array<void *> h00B8;
|
||||
/* +h00C8 */ uint32_t rand1; // Number seems to be randomized quite a bit o.o seems to be accessed by textparser.cpp
|
||||
/* +h00CC */ uint32_t rand2;
|
||||
/* +h00D0 */ uint8_t h00D0[24];
|
||||
/* +h00E8 */ Array<AgentMovement *> agent_movement;
|
||||
/* +h00F8 */ Array<void *> h00F8;
|
||||
/* +h0108 */ uint32_t h0108[0x11];
|
||||
/* +h014C */ Array<void *> agent_array1;
|
||||
/* +h015C */ Array<void *> agent_async_movement;
|
||||
/* +h016C */ uint32_t h016C[0x10];
|
||||
/* +h01AC */ uint32_t instance_timer;
|
||||
//... more but meh
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
#include <GWCA/Utilities/Export.h>
|
||||
|
||||
namespace GW {
|
||||
namespace Constants {
|
||||
enum class Language;
|
||||
enum class MapID : uint32_t;
|
||||
enum class InstanceType;
|
||||
}
|
||||
struct CharContext;
|
||||
GWCA_API CharContext* GetCharContext();
|
||||
|
||||
struct ObserverMatch;
|
||||
|
||||
struct ProgressBarContext {
|
||||
int pips;
|
||||
uint8_t color[4]; // RGBA
|
||||
uint8_t background[4]; // RGBA
|
||||
int unk[7];
|
||||
float progress; // 0 ... 1
|
||||
// possibly more
|
||||
};
|
||||
|
||||
struct CharContext { // total: 0x42C
|
||||
/* +h0000 */ Array<void *> h0000;
|
||||
/* +h0010 */ uint32_t h0010;
|
||||
/* +h0014 */ Array<void *> h0014;
|
||||
/* +h0024 */ uint32_t h0024[4];
|
||||
/* +h0034 */ Array<void *> h0034;
|
||||
/* +h0044 */ Array<void *> h0044;
|
||||
/* +h0054 */ uint32_t h0054[4]; // load head variables
|
||||
/* +h0064 */ uint32_t player_uuid[4]; // uuid
|
||||
/* +h0074 */ wchar_t player_name[0x14];
|
||||
/* +h009C */ uint32_t h009C[20];
|
||||
/* +h00EC */ Array<void *> h00EC;
|
||||
/* +h00FC */ uint32_t h00FC[37]; // 40
|
||||
/* +h0190 */ uint32_t world_flags;
|
||||
/* +h0194 */ uint32_t token1; // world id
|
||||
/* +h0198 */ GW::Constants::MapID map_id;
|
||||
/* +h019C */ uint32_t is_explorable;
|
||||
/* +h01A0 */ uint8_t host[0x18];
|
||||
/* +h01B8 */ uint32_t token2; // player id
|
||||
/* +h01BC */ uint32_t h01BC[25];
|
||||
/* +h0220 */ uint32_t district_number;
|
||||
/* +h0224 */ GW::Constants::Language language;
|
||||
/* +h0228 */ GW::Constants::MapID observe_map_id;
|
||||
/* +h022C */ GW::Constants::MapID current_map_id;
|
||||
/* +h0230 */ Constants::InstanceType observe_map_type;
|
||||
/* +h0234 */ Constants::InstanceType current_map_type;
|
||||
/* +h0238 */ uint32_t h0238[5];
|
||||
/* +h024C */ Array<ObserverMatch*> observer_matches;
|
||||
/* +h025C */ uint32_t h025C[17];
|
||||
/* +h02a0 */ uint32_t player_flags; // bitwise something
|
||||
/* +h02A4 */ uint32_t player_number;
|
||||
/* +h02A8 */ uint32_t h02A8[40];
|
||||
/* +h0348 */ ProgressBarContext* progress_bar; // seems to never be nullptr
|
||||
/* +h034C */ uint32_t h034C[27];
|
||||
/* +h03B8 */ wchar_t player_email[0x40];
|
||||
};
|
||||
static_assert(sizeof(CharContext) == 0x438, "struct CharContext has incorrect size");
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
namespace GW {
|
||||
struct Cinematic {
|
||||
/* +h0000 */ uint32_t h0000;
|
||||
/* +h0004 */ uint32_t h0004; // pointer to data
|
||||
// ...
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
|
||||
namespace GW {
|
||||
struct GadgetInfo {
|
||||
/* +h0000 */ uint32_t h0000;
|
||||
/* +h0004 */ uint32_t h0004;
|
||||
/* +h0008 */ uint32_t h0008;
|
||||
/* +h000C */ wchar_t *name_enc;
|
||||
};
|
||||
|
||||
struct GadgetContext {
|
||||
/* +h0000 */ Array<GadgetInfo> GadgetInfo;
|
||||
// ...
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
#include <GWCA/Utilities/Export.h>
|
||||
|
||||
namespace GW {
|
||||
struct GameContext;
|
||||
GWCA_API GameContext* GetGameContext();
|
||||
|
||||
struct Cinematic;
|
||||
struct MapContext;
|
||||
struct TextParser;
|
||||
struct CharContext;
|
||||
struct ItemContext;
|
||||
struct AgentContext;
|
||||
struct GuildContext;
|
||||
struct PartyContext;
|
||||
struct TradeContext;
|
||||
struct WorldContext;
|
||||
struct GadgetContext;
|
||||
struct AccountContext;
|
||||
struct EventContext;
|
||||
|
||||
struct GameContext {
|
||||
/* +h0000 */ void* h0000;
|
||||
/* +h0004 */ void* h0004;
|
||||
/* +h0008 */ AgentContext* agent; // Most functions that access are prefixed with Agent.
|
||||
/* +h000C */ EventContext* event;
|
||||
/* +h0010 */ void* h0010;
|
||||
/* +h0014 */ MapContext* map; // Static object/collision data
|
||||
/* +h0018 */ TextParser *text_parser;
|
||||
/* +h001C */ void* h001C;
|
||||
/* +h0020 */ uint32_t some_number; // 0x30 for me at the moment.
|
||||
/* +h0024 */ void* h0024;
|
||||
/* +h0028 */ AccountContext* account;
|
||||
/* +h002C */ WorldContext* world; // Best name to fit it that I can think of.
|
||||
/* +h0030 */ Cinematic *cinematic;
|
||||
/* +h0034 */ void* h0034;
|
||||
/* +h0038 */ GadgetContext* gadget;
|
||||
/* +h003C */ GuildContext* guild;
|
||||
/* +h0040 */ ItemContext* items;
|
||||
/* +h0044 */ CharContext* character;
|
||||
/* +h0048 */ void* h0048;
|
||||
/* +h004C */ PartyContext* party;
|
||||
/* +h0050 */ void* h0050;
|
||||
/* +h0054 */ void* h0054;
|
||||
/* +h0058 */ TradeContext* trade;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <GWCA/Utilities/Export.h>
|
||||
|
||||
namespace GW {
|
||||
struct GameplayContext;
|
||||
GWCA_API GameplayContext* GetGameplayContext();
|
||||
|
||||
// Static stuff used at runtime
|
||||
struct GameplayContext {
|
||||
/* +h0000 */ uint32_t h0000[0x13];
|
||||
float mission_map_zoom;
|
||||
uint32_t unk[10];
|
||||
};
|
||||
static_assert(sizeof(GameplayContext) == 0x78);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <GWCA/GameEntities/Guild.h>
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
#include <GWCA/Utilities/Export.h>
|
||||
|
||||
namespace GW {
|
||||
struct GuildContext;
|
||||
GWCA_API GuildContext* GetGuildContext();
|
||||
|
||||
typedef Array<Guild *> GuildArray;
|
||||
typedef Array<GuildPlayer *> GuildRoster;
|
||||
typedef Array<GuildHistoryEvent *> GuildHistory;
|
||||
|
||||
struct GuildContext { // total: 0x3BC/956
|
||||
/* +h0000 */ uint32_t h0000;
|
||||
/* +h0004 */ uint32_t h0004;
|
||||
/* +h0008 */ uint32_t h0008;
|
||||
/* +h000C */ uint32_t h000C;
|
||||
/* +h0010 */ uint32_t h0010;
|
||||
/* +h0014 */ uint32_t h0014;
|
||||
/* +h0018 */ uint32_t h0018;
|
||||
/* +h001C */ uint32_t h001C;
|
||||
/* +h0020 */ Array<void *> h0020;
|
||||
/* +h0030 */ uint32_t h0030;
|
||||
/* +h0034 */ wchar_t player_name[20];
|
||||
/* +h005C */ uint32_t h005C;
|
||||
/* +h0060 */ uint32_t player_guild_index;
|
||||
/* +h0064 */ GHKey player_gh_key;
|
||||
/* +h0074 */ uint32_t h0074;
|
||||
/* +h0078 */ wchar_t announcement[256];
|
||||
/* +h0278 */ wchar_t announcement_author[20];
|
||||
/* +h02A0 */ uint32_t player_guild_rank;
|
||||
/* +h02A4 */ uint32_t h02A4;
|
||||
/* +h02A8 */ Array<TownAlliance> factions_outpost_guilds;
|
||||
/* +h02B8 */ uint32_t kurzick_town_count;
|
||||
/* +h02BC */ uint32_t luxon_town_count;
|
||||
/* +h02C0 */ uint32_t h02C0;
|
||||
/* +h02C4 */ uint32_t h02C4;
|
||||
/* +h02C8 */ uint32_t h02C8;
|
||||
/* +h02CC */ GuildHistory player_guild_history;
|
||||
/* +h02DC */ uint32_t h02DC[7];
|
||||
/* +h02F8 */ GuildArray guilds;
|
||||
/* +h0308 */ uint32_t h0308[4];
|
||||
/* +h0318 */ Array<void *> h0318;
|
||||
/* +h0328 */ uint32_t h0328;
|
||||
/* +h032C */ Array<void *> h032C;
|
||||
/* +h033C */ uint32_t h033C[7];
|
||||
/* +h0358 */ GuildRoster player_roster;
|
||||
//... end of what i care about
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
#include <GWCA/Utilities/Export.h>
|
||||
|
||||
namespace GW {
|
||||
struct ItemContext;
|
||||
GWCA_API ItemContext* GetItemContext();
|
||||
|
||||
struct Bag;
|
||||
struct Item;
|
||||
struct Inventory;
|
||||
|
||||
struct ItemContext { // total: 0x10C/268 BYTEs
|
||||
/* +h0000 */ Array<void *> h0000;
|
||||
/* +h0010 */ Array<void *> h0010;
|
||||
/* +h0020 */ DWORD h0020;
|
||||
/* +h0024 */ Array<Bag *> bags_array;
|
||||
/* +h0034 */ char h0034[12];
|
||||
/* +h0040 */ Array<void *> h0040;
|
||||
/* +h0050 */ Array<void *> h0050;
|
||||
/* +h0060 */ char h0060[88];
|
||||
/* +h00B8 */ Array<Item *> item_array;
|
||||
/* +h00C8 */ char h00C8[48];
|
||||
/* +h00F8 */ Inventory *inventory;
|
||||
/* +h00FC */ Array<void *> h00FC;
|
||||
};
|
||||
}
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
#pragma once
|
||||
|
||||
#include <GWCA/GameContainers/List.h>
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
#include <GWCA/GameContainers/ObjectPool.h>
|
||||
#include <GWCA/GameContainers/PrioQ.h>
|
||||
#include <GWCA/Utilities/Export.h>
|
||||
|
||||
namespace GW {
|
||||
struct PathingMap;
|
||||
struct MapProp;
|
||||
struct PropByType;
|
||||
struct PropModelInfo;
|
||||
namespace Constants {
|
||||
enum class MapID : uint32_t;
|
||||
}
|
||||
|
||||
typedef Array<PathingMap> PathingMapArray;
|
||||
|
||||
struct PropsContext {
|
||||
/* +h0000 */ uint32_t pad1[0x1b];
|
||||
/* +h006C */ Array<TList<PropByType>> propsByType;
|
||||
/* +h007C */ uint32_t h007C[0xa];
|
||||
/* +h00A4 */ Array<PropModelInfo> propModels;
|
||||
/* +h00B4 */ uint32_t h00B4[0x38];
|
||||
/* +h0194 */ Array<MapProp*> propArray;
|
||||
};
|
||||
static_assert(sizeof(PropsContext) == 0x1A4, "struct PropsContext has incorrect size");
|
||||
|
||||
struct MapStaticData {
|
||||
/* +h0000 */ uint32_t h0000;
|
||||
/* +h0004 */ uint32_t h0004;
|
||||
/* +h0008 */ uint32_t h0008;
|
||||
/* +h000C */ uint32_t h000C;
|
||||
/* +h0010 */ uint32_t h0010;
|
||||
/* +h0014 */ uint32_t trapezoidCount;
|
||||
/* +h0018 */ PathingMapArray map;
|
||||
/* +h0028 */ uint32_t h0028;
|
||||
/* +h002C */ uint32_t h002C;
|
||||
/* +h0030 */ uint32_t h0030;
|
||||
/* +h0034 */ uint32_t h0034;
|
||||
/* +h0038 */ uint32_t h0038;
|
||||
/* +h003C */ uint32_t h003C;
|
||||
/* +h0040 */ uint32_t h0040;
|
||||
/* +h0044 */ uint32_t h0044;
|
||||
/* +h0048 */ uint32_t h0048;
|
||||
/* +h004C */ uint32_t h004C;
|
||||
/* +h0050 */ uint32_t h0050;
|
||||
/* +h0054 */ uint32_t h0054;
|
||||
/* +h0058 */ uint32_t h0058;
|
||||
/* +h005C */ uint32_t h005C;
|
||||
/* +h0060 */ uint32_t h0060;
|
||||
/* +h0064 */ uint32_t h0064;
|
||||
/* +h0068 */ uint32_t h0068;
|
||||
/* +h006C */ uint32_t h006C;
|
||||
/* +h0070 */ uint32_t h0070;
|
||||
/* +h0074 */ uint32_t h0074;
|
||||
/* +h0078 */ uint32_t h0078;
|
||||
/* +h007C */ uint32_t h007C;
|
||||
/* +h0080 */ uint32_t h0080;
|
||||
/* +h0084 */ uint32_t nextTrapezoidId; // Starts at 0, increment everytime a trapezoid is created. It's used to assign a unique trapezoid id to every trapezoid. Used for path finding.
|
||||
/* +h0088 */ uint32_t h0088;
|
||||
/* +h008C */ GW::Constants::MapID map_id;
|
||||
/* +h0090 */ uint32_t h0090;
|
||||
/* +h0094 */ uint32_t h0094;
|
||||
/* +h0098 */ uint32_t h0098;
|
||||
/* +h009C */ uint32_t h009C;
|
||||
};
|
||||
static_assert(sizeof(MapStaticData) == 0xA0, "struct MapStaticData has incorrect size");
|
||||
|
||||
// Those are planes that are blocked and can be unblocked at runtime. e.g., the gates in foundry
|
||||
// Those aren't in the dat file, but sent from the server
|
||||
typedef BaseArray<uint32_t> BlockedPlaneArray;
|
||||
static_assert(sizeof(BlockedPlaneArray) == 0xC, "struct BlockedPlaneArray has incorrect size");
|
||||
|
||||
// The game leak this type name and it's `IPath::PathNode`
|
||||
struct PathNode {
|
||||
/* +h0000 */ uint32_t closed;
|
||||
/* +h0004 */ float costToNode;
|
||||
/* +h0008 */ PrioQLink<PathNode*> priority;
|
||||
/* +h0018 */ GamePos nodePos; // This position is a guess on the best position to pass through. It's usually on one of the 4 edges of a trapezoid.
|
||||
/* +h0024 */ struct PathingTrapezoid *currentTrapezoid;
|
||||
/* +h0028 */ PathNode *parentPathMap;
|
||||
};
|
||||
static_assert(sizeof(PathNode) == 0x2C, "struct PathNode has incorrect size");
|
||||
|
||||
typedef BaseArray<PathNode*> PathNodeArray;
|
||||
static_assert(sizeof(PathNodeArray) == 0xC, "struct PathNodeArray has incorrect size");
|
||||
|
||||
struct NodeCache {
|
||||
/* +h0000 */ uint32_t* cachedCount;
|
||||
/* +h0004 */ uint32_t m_mask;
|
||||
/* +h0008 */ BaseArray<uint32_t> buffer;
|
||||
};
|
||||
static_assert(sizeof(NodeCache) == 0x14, "struct NodeCache has incorrect size");
|
||||
|
||||
struct PathWaypoint {
|
||||
/* +h0000 */ float x;
|
||||
/* +h0004 */ float y;
|
||||
/* +h0008 */ float width;
|
||||
/* +h000C */ float height;
|
||||
/* +h0010 */ uint32_t plane;
|
||||
/* +h0014 */ PathingTrapezoid *nextTrap;
|
||||
};
|
||||
static_assert(sizeof(PathWaypoint) == 0x18, "struct PathWaypoint has incorrect size");
|
||||
|
||||
struct PathContext {
|
||||
/* +h0000 */ MapStaticData* staticData;
|
||||
/* +h0004 */ BlockedPlaneArray blockedPlanes;
|
||||
/* +h0010 */ PathNodeArray pathNodes; // This array of pathNodes are indexed with the trapezoid id.
|
||||
/* +h001C */ NodeCache nodeCache;
|
||||
/* +h0030 */ PrioQ<PathNode> openList;
|
||||
/* +h0044 */ ObjectPool freeIPathNode;
|
||||
/* +h0050 */ PathNodeArray allocatedPathNodes; // This is just an array of all allocated path nodes used to cleanup. The order is the allocation order.
|
||||
/* +h005C */ uint32_t h005C;
|
||||
/* +h0060 */ uint32_t h0060;
|
||||
/* +h0064 */ Array<PathWaypoint> waypoints;
|
||||
/* +h0074 */ Array<struct Node*> nodeStack;
|
||||
/* +h0084 */ uint32_t h0084;
|
||||
/* +h0088 */ uint32_t h0088;
|
||||
/* +h008C */ uint32_t h008C;
|
||||
/* +h0090 */ uint32_t h0090;
|
||||
};
|
||||
static_assert(sizeof(PathContext) == 0x94, "struct PathContext has incorrect size");
|
||||
|
||||
// The game can optionally load a DLL to do the path finding.
|
||||
// The DLL is named "PathEngine.dll", but not clear if it's a 3rd party or just their name
|
||||
// for development.
|
||||
struct PathEngineContext {
|
||||
/* +h0000 */ void **vtable;
|
||||
/* +h0004 */ uint32_t h0004;
|
||||
/* +h0008 */ uint32_t h0008;
|
||||
/* +h000C */ void *user_data;
|
||||
/* +h0010 */ HMODULE hDll;
|
||||
/* +h0014 */ uint32_t pfnCreateInterface;
|
||||
};
|
||||
static_assert(sizeof(PathEngineContext) == 0x18, "struct PathEngineContext has incorrect size");
|
||||
|
||||
struct MapContext {
|
||||
/* +h0000 */ uint32_t map_type; // less than 4
|
||||
/* +h0004 */ Vec2f start_pos;
|
||||
/* +h000c */ Vec2f end_pos;
|
||||
/* +h0014 */ uint32_t h0014[6];
|
||||
/* +h002C */ Array<void*> spawns1; // Seem to be arena spawns. struct is X,Y,unk 4 byte value,unk 4 byte value.
|
||||
/* +h003C */ Array<void*> spawns2; // Same as above
|
||||
/* +h004C */ Array<void*> spawns3; // Same as above
|
||||
/* +h005C */ float h005C[6]; // Some trapezoid i think.
|
||||
/* +h0074 */ PathContext* path;
|
||||
/* +h0078 */ PathEngineContext* path_engine;
|
||||
/* +h007C */ PropsContext* props;
|
||||
/* +h0080 */ uint32_t h0080;
|
||||
/* +h0084 */ void* terrain;
|
||||
/* +h0088 */ uint32_t h0088;
|
||||
/* +h008C */ GW::Constants::MapID map_id;
|
||||
/* +h0090 */ uint32_t h0090;
|
||||
/* +h0094 */ uint32_t h0094;
|
||||
/* +h0098 */ uint32_t h0098;
|
||||
/* +h009C */ uint32_t h009C;
|
||||
/* +h00A0 */ uint32_t h00A0;
|
||||
/* +h00A4 */ uint32_t h00A4;
|
||||
/* +h00A8 */ uint32_t h00A8;
|
||||
/* +h00AC */ uint32_t h00AC;
|
||||
/* +h00B0 */ uint32_t h00B0;
|
||||
/* +h00B4 */ uint32_t h00B4;
|
||||
/* +h00B8 */ uint32_t h00B8;
|
||||
/* +h00BC */ uint32_t h00BC;
|
||||
/* +h00C0 */ uint32_t h00C0;
|
||||
/* +h00C4 */ uint32_t h00C4;
|
||||
/* +h00C8 */ uint32_t h00C8;
|
||||
/* +h00CC */ uint32_t h00CC;
|
||||
/* +h00D0 */ uint32_t h00D0;
|
||||
/* +h00D4 */ uint32_t h00D4;
|
||||
/* +h00D8 */ uint32_t h00D8;
|
||||
/* +h00DC */ uint32_t h00DC;
|
||||
/* +h00E0 */ uint32_t h00E0;
|
||||
/* +h00E4 */ uint32_t h00E4;
|
||||
/* +h00E8 */ uint32_t h00E8;
|
||||
/* +h00EC */ uint32_t h00EC;
|
||||
/* +h00F0 */ uint32_t h00F0;
|
||||
/* +h00F4 */ uint32_t h00F4;
|
||||
/* +h00F8 */ uint32_t h00F8;
|
||||
/* +h00FC */ uint32_t h00FC;
|
||||
/* +h0100 */ uint32_t h0100;
|
||||
/* +h0104 */ uint32_t h0104;
|
||||
/* +h0108 */ uint32_t h0108;
|
||||
/* +h010C */ uint32_t h010C;
|
||||
/* +h0110 */ uint32_t h0110;
|
||||
/* +h0114 */ uint32_t h0114;
|
||||
/* +h0118 */ uint32_t h0118;
|
||||
/* +h011C */ uint32_t h011C;
|
||||
/* +h0120 */ uint32_t h0120;
|
||||
/* +h0124 */ uint32_t h0124;
|
||||
/* +h0128 */ uint32_t h0128;
|
||||
/* +h012C */ uint32_t h012C;
|
||||
/* +h0130 */ void* zones;
|
||||
/* +h0134 */ uint32_t h0134;
|
||||
};
|
||||
static_assert(sizeof(MapContext) == 0x138, "struct MapContext has incorrect size");
|
||||
GWCA_API MapContext* GetMapContext();
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <GWCA/GameContainers/List.h>
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
#include <GWCA/Utilities/Export.h>
|
||||
|
||||
namespace GW {
|
||||
struct PartyContext;
|
||||
GWCA_API PartyContext* GetPartyContext();
|
||||
|
||||
struct PartyInfo;
|
||||
struct PartySearch;
|
||||
|
||||
struct PartySearchContext {
|
||||
uint32_t h0000;
|
||||
uint32_t h0004;
|
||||
uint32_t h0008;
|
||||
uint32_t h000c;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct PartyContext { // total: 0x58/88
|
||||
/* +h0000 */ uint32_t h0000;
|
||||
/* +h0004 */ Array<void*> h0004;
|
||||
/* +h0014 */ uint32_t flag;
|
||||
/* +h0018 */ uint32_t h0018;
|
||||
/* +h001C */ TList<PartyInfo> requests;
|
||||
/* +h0028 */ uint32_t requests_count;
|
||||
/* +h002C */ TList<PartyInfo> sending;
|
||||
/* +h0038 */ uint32_t sending_count;
|
||||
/* +h003C */ uint32_t h003C;
|
||||
/* +h0040 */ Array<PartyInfo*> parties;
|
||||
/* +h0050 */ uint32_t h0050;
|
||||
/* +h0054 */ PartyInfo* player_party; // Players party
|
||||
/* +h0058 */ uint32_t h0058[17];
|
||||
/* +h009C */ uint32_t my_party_search_id;
|
||||
/* +h00A0 */ uint32_t h00A0[8];
|
||||
/* +h00C0 */ Array<PartySearch*> party_search;
|
||||
|
||||
bool InHardMode() const { return (flag & 0x10) > 0; }
|
||||
bool IsDefeated() const { return (flag & 0x20) > 0; }
|
||||
bool IsPartyLeader() const { return (flag >> 0x7) & 1; }
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
#include <GWCA/Utilities/Export.h>
|
||||
|
||||
namespace GW {
|
||||
struct PreGameContext;
|
||||
struct CharacterInformation;
|
||||
GWCA_API PreGameContext* GetPreGameContext();
|
||||
GWCA_API Array<CharacterInformation>* GetAvailableChars();
|
||||
|
||||
struct LoginCharacter {
|
||||
uint32_t unk0; // Some kind of function call
|
||||
wchar_t character_name[20];
|
||||
};
|
||||
|
||||
// Character information available at login screen
|
||||
struct CharacterInformation {
|
||||
/* +h0000 */ uint32_t h0000[2];
|
||||
/* +h0008 */ uint32_t uuid[4];
|
||||
/* +h0018 */ wchar_t name[20];
|
||||
/* +h0040 */ uint32_t props[17];
|
||||
|
||||
uint32_t GetMapId() const { return (props[0] >> 16) & 0xFFFF; }
|
||||
uint32_t GetPrimaryProfession() const { return (props[2] >> 20) & 0xF; }
|
||||
uint32_t GetSecondaryProfession() const { return (props[7] >> 10) & 0xF; }
|
||||
uint32_t GetCampaign() const { return props[7] & 0xF; }
|
||||
uint32_t GetLevel() const { return (props[7] >> 4) & 0x3F; }
|
||||
bool IsPvP() const { return ((props[7] >> 9) & 0x1) == 0x1; }
|
||||
};
|
||||
struct PreGameContext {
|
||||
/* +h0000 */ uint32_t frame_id;
|
||||
/* +h0004 */ uint32_t h0004[72];
|
||||
/* +h0124 */ uint32_t chosen_character_index;
|
||||
/* +h0128 */ uint32_t h0128[6];
|
||||
/* +h0140 */ uint32_t index_1;
|
||||
/* +h0144 */ uint32_t index_2;
|
||||
/* +h0148 */ GW::Array<LoginCharacter> chars;
|
||||
};
|
||||
}
|
||||
// ============================================================
|
||||
// C Interop API
|
||||
// ============================================================
|
||||
extern "C" {
|
||||
GWCA_API void* GetAvailableChars();
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
|
||||
namespace GW {
|
||||
namespace Constants {
|
||||
enum class Language;
|
||||
}
|
||||
struct TextCache {
|
||||
/* +h0000 */ uint32_t h0000;
|
||||
};
|
||||
|
||||
struct SubStruct1 {
|
||||
/* +h0000 */ uint32_t h0000;
|
||||
};
|
||||
|
||||
// Allocated @0078C243
|
||||
struct SubStructUnk { // total: 0x54/84
|
||||
/* +h0000 */ uint32_t AsyncDecodeStr_Callback;
|
||||
/* +h0004 */ uint32_t AsyncDecodeStr_Param;
|
||||
/* +h0008 */ uint32_t buffer_used; // if it's 1 then uses s1 & if it's 0 uses s2.
|
||||
/* +h000C */ Array<wchar_t> s1;
|
||||
/* +h001C */ Array<wchar_t> s2;
|
||||
/* +h002C */ uint32_t h002C;
|
||||
/* +h0030 */ uint32_t h0030; // tell us how many string will be enqueue before decoding.
|
||||
/* +h0034 */ uint32_t h0034; // @0078B990
|
||||
/* +h0038 */ uint8_t h0038[28];
|
||||
};
|
||||
|
||||
struct TextParser {
|
||||
/* +h0000 */ uint32_t h0000[8];
|
||||
/* +h0020 */ wchar_t *dec_start;
|
||||
/* +h0024 */ wchar_t *dec_end;
|
||||
/* +h0028 */ uint32_t substitute_1; // related to h0020 & h0024
|
||||
/* +h002C */ uint32_t substitute_2; // related to h0020 & h0024
|
||||
/* +h0030 */ TextCache *cache;
|
||||
/* +h0034 */ uint32_t h0034[75];
|
||||
/* +h0160 */ uint32_t h0160; // @0078BEF5
|
||||
/* +h0164 */ uint32_t h0164;
|
||||
/* +h0168 */ uint32_t h0168; // set to 0 @0078BF34
|
||||
/* +h016C */ uint32_t h016C[5];
|
||||
/* +h0180 */ SubStruct1 *sub_struct;
|
||||
/* +h0184 */ uint32_t h0184[19];
|
||||
/* +h01d0 */ GW::Constants::Language language_id;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
|
||||
|
||||
namespace GW {
|
||||
|
||||
struct TradeItem {
|
||||
uint32_t item_id;
|
||||
uint32_t quantity;
|
||||
};
|
||||
struct TradePlayer {
|
||||
uint32_t gold;
|
||||
Array<TradeItem> items;
|
||||
};
|
||||
|
||||
struct TradeContext {
|
||||
enum TradeStatus {
|
||||
TRADE_CLOSED = 0,
|
||||
TRADE_INITIATED = 1,
|
||||
TRADE_OFFER_SEND = 2,
|
||||
TRADE_ACCEPTED = 4
|
||||
};
|
||||
|
||||
/* +h0000 */ uint32_t flags; // this is actually a flags
|
||||
/* +h0004 */ uint32_t h0004[3]; // Seemingly 3 null dwords
|
||||
/* +h0010 */ TradePlayer player;
|
||||
/* +h0024 */ TradePlayer partner;
|
||||
|
||||
// bool GetPartnerAccepted();
|
||||
// bool GetPartnerOfferSent();
|
||||
|
||||
bool GetIsTradeOffered() const { return (flags & TRADE_OFFER_SEND) != 0; }
|
||||
bool GetIsTradeInitiated() const { return (flags & TRADE_INITIATED) != 0; }
|
||||
bool GetIsTradeAccepted() const { return (flags & TRADE_ACCEPTED) != 0; }
|
||||
};
|
||||
|
||||
GWCA_API TradeContext* GetTradeContext();
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
#pragma once
|
||||
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
#include <GWCA/GameContainers/GamePos.h>
|
||||
#include <GWCA/Utilities/Export.h>
|
||||
|
||||
namespace GW {
|
||||
struct WorldContext;
|
||||
GWCA_API WorldContext* GetWorldContext();
|
||||
|
||||
namespace Constants {
|
||||
enum class Profession : uint32_t;
|
||||
}
|
||||
|
||||
typedef uint32_t ItemID;
|
||||
enum class HeroBehavior : uint32_t;
|
||||
|
||||
|
||||
struct NPC;
|
||||
struct Quest;
|
||||
struct Title;
|
||||
struct Player;
|
||||
struct HeroInfo;
|
||||
struct HeroFlag;
|
||||
struct MapAgent;
|
||||
struct Skillbar;
|
||||
struct AgentInfo;
|
||||
struct AgentEffects;
|
||||
struct PartyAttribute;
|
||||
struct MissionMapIcon;
|
||||
struct MissionObjective;
|
||||
struct TitleTier;
|
||||
|
||||
typedef Array<NPC> NPCArray;
|
||||
typedef Array<Quest> QuestLog;
|
||||
typedef Array<Title> TitleArray;
|
||||
typedef Array<ItemID> MerchItemArray;
|
||||
typedef Array<Player> PlayerArray;
|
||||
typedef Array<HeroFlag> HeroFlagArray;
|
||||
typedef Array<HeroInfo> HeroInfoArray;
|
||||
typedef Array<MapAgent> MapAgentArray;
|
||||
typedef Array<Skillbar> SkillbarArray;
|
||||
typedef Array<AgentInfo> AgentInfoArray;
|
||||
typedef Array<AgentEffects> AgentEffectsArray;
|
||||
typedef Array<MissionMapIcon> MissionMapIconArray;
|
||||
typedef Array<PartyAttribute> PartyAttributeArray;
|
||||
|
||||
struct PartyAlly {
|
||||
uint32_t agent_id;
|
||||
uint32_t unk;
|
||||
uint32_t composite_id;
|
||||
};
|
||||
static_assert(sizeof(PartyAlly) == 0xc);
|
||||
|
||||
namespace Constants {
|
||||
enum class QuestID : uint32_t;
|
||||
}
|
||||
|
||||
struct ControlledMinions {
|
||||
uint32_t agent_id;
|
||||
uint32_t minion_count;
|
||||
};
|
||||
struct DupeSkill {
|
||||
uint32_t skill_id;
|
||||
uint32_t count;
|
||||
};
|
||||
struct ProfessionState {
|
||||
uint32_t agent_id;
|
||||
GW::Constants::Profession primary;
|
||||
GW::Constants::Profession secondary;
|
||||
uint32_t unlocked_professions; // bitwise
|
||||
uint32_t unk;
|
||||
|
||||
inline bool IsProfessionUnlocked(GW::Constants::Profession profession) const {
|
||||
return (unlocked_professions & (1 << (uint32_t)profession)) != 0;
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(ProfessionState) == 0x14);
|
||||
|
||||
struct AccountInfo {
|
||||
wchar_t* account_name;
|
||||
uint32_t wins;
|
||||
uint32_t losses;
|
||||
uint32_t rating;
|
||||
uint32_t qualifier_points;
|
||||
uint32_t rank;
|
||||
uint32_t tournament_reward_points;
|
||||
};
|
||||
static_assert(sizeof(AccountInfo) == 0x1c);
|
||||
|
||||
struct PartyMemberMoraleInfo {
|
||||
uint32_t agent_id;
|
||||
uint32_t agent_id_dup;
|
||||
uint32_t unk[4];
|
||||
uint32_t morale;
|
||||
// ... unknown size
|
||||
};
|
||||
|
||||
struct PartyMoraleLink {
|
||||
uint32_t unk;
|
||||
uint32_t unk2;
|
||||
PartyMemberMoraleInfo* party_member_info;
|
||||
};
|
||||
static_assert(sizeof(PartyMoraleLink) == 0xc);
|
||||
|
||||
struct PetInfo {
|
||||
uint32_t agent_id;
|
||||
uint32_t owner_agent_id;
|
||||
wchar_t* pet_name;
|
||||
uint32_t model_file_id1;
|
||||
uint32_t model_file_id2;
|
||||
HeroBehavior behavior;
|
||||
uint32_t locked_target_id;
|
||||
|
||||
};
|
||||
static_assert(sizeof(PetInfo) == 0x1c);
|
||||
|
||||
struct PlayerControlledCharacter {
|
||||
uint32_t field0_0x0;
|
||||
uint32_t field1_0x4;
|
||||
uint32_t field2_0x8;
|
||||
uint32_t field3_0xc;
|
||||
uint32_t field4_0x10;
|
||||
uint32_t agent_id;
|
||||
uint32_t composite_id; // 0x30000000 | player_number
|
||||
uint32_t field7_0x1c;
|
||||
uint32_t field8_0x20;
|
||||
uint32_t field9_0x24;
|
||||
uint32_t field10_0x28;
|
||||
uint32_t field11_0x2c;
|
||||
uint32_t field12_0x30;
|
||||
uint32_t field13_0x34;
|
||||
uint32_t field14_0x38;
|
||||
uint32_t field15_0x3c;
|
||||
uint32_t field16_0x40;
|
||||
uint32_t field17_0x44;
|
||||
uint32_t field18_0x48;
|
||||
uint32_t field19_0x4c;
|
||||
uint32_t field20_0x50;
|
||||
uint32_t field21_0x54;
|
||||
uint32_t field22_0x58;
|
||||
uint32_t field23_0x5c;
|
||||
uint32_t field24_0x60;
|
||||
uint32_t more_flags;
|
||||
uint32_t field26_0x68;
|
||||
uint32_t field27_0x6c;
|
||||
uint32_t field28_0x70;
|
||||
uint32_t field29_0x74;
|
||||
uint32_t field30_0x78;
|
||||
uint32_t field31_0x7c;
|
||||
uint32_t field32_0x80;
|
||||
uint32_t field33_0x84;
|
||||
uint32_t field34_0x88;
|
||||
uint32_t field35_0x8c;
|
||||
uint32_t field36_0x90;
|
||||
uint32_t field37_0x94;
|
||||
uint32_t field38_0x98;
|
||||
uint32_t field39_0x9c;
|
||||
uint32_t field40_0xa0;
|
||||
uint32_t field41_0xa4;
|
||||
uint32_t field42_0xa8;
|
||||
uint32_t field43_0xac;
|
||||
uint32_t field44_0xb0;
|
||||
uint32_t field45_0xb4;
|
||||
uint32_t field46_0xb8;
|
||||
uint32_t field47_0xbc;
|
||||
uint32_t field48_0xc0;
|
||||
uint32_t field49_0xc4;
|
||||
uint32_t field50_0xc8;
|
||||
uint32_t field51_0xcc;
|
||||
uint32_t field52_0xd0;
|
||||
uint32_t field53_0xd4;
|
||||
uint32_t field54_0xd8;
|
||||
uint32_t field55_0xdc;
|
||||
uint32_t field56_0xe0;
|
||||
uint32_t field57_0xe4;
|
||||
uint32_t field58_0xe8;
|
||||
uint32_t field59_0xec;
|
||||
uint32_t field60_0xf0;
|
||||
uint32_t field61_0xf4;
|
||||
uint32_t field62_0xf8;
|
||||
uint32_t field63_0xfc;
|
||||
uint32_t field64_0x100;
|
||||
uint32_t field65_0x104;
|
||||
uint32_t field66_0x108;
|
||||
uint32_t flags;
|
||||
uint32_t field68_0x110;
|
||||
uint32_t field69_0x114;
|
||||
uint32_t field70_0x118;
|
||||
uint32_t field71_0x11c;
|
||||
uint32_t field72_0x120;
|
||||
uint32_t field73_0x124;
|
||||
uint32_t field74_0x128;
|
||||
uint32_t field75_0x12c;
|
||||
uint32_t field76_0x130;
|
||||
};
|
||||
static_assert(sizeof(PlayerControlledCharacter) == 0x134);
|
||||
|
||||
|
||||
struct WorldContext {
|
||||
/* +h0000 */ AccountInfo* accountInfo;
|
||||
/* +h0004 */ Array<wchar_t> message_buff;
|
||||
/* +h0014 */ Array<wchar_t> dialog_buff;
|
||||
/* +h0024 */ MerchItemArray merch_items;
|
||||
/* +h0034 */ MerchItemArray merch_items2;
|
||||
/* +h0044 */ uint32_t accumMapInitUnk0;
|
||||
/* +h0048 */ uint32_t accumMapInitUnk1;
|
||||
/* +h004C */ uint32_t accumMapInitOffset;
|
||||
/* +h0050 */ uint32_t accumMapInitLength;
|
||||
/* +h0054 */ uint32_t h0054;
|
||||
/* +h0058 */ uint32_t accumMapInitUnk2;
|
||||
/* +h005C */ uint32_t h005C[8];
|
||||
/* +h007C */ MapAgentArray map_agents;
|
||||
/* +h008C */ Array<PartyAlly> party_allies; // List of allies added to the current party
|
||||
/* +h009C */ Vec3f all_flag;
|
||||
/* +h00A8 */ uint32_t h00A8;
|
||||
/* +h00AC */ PartyAttributeArray attributes;
|
||||
/* +h00BC */ uint32_t h00BC[255];
|
||||
/* +h04B8 */ Array<void *> h04B8;
|
||||
/* +h04C8 */ Array<void *> h04C8;
|
||||
/* +h04D8 */ uint32_t h04D8;
|
||||
/* +h04DC */ Array<void *> h04DC;
|
||||
/* +h04EC */ uint32_t h04EC[7];
|
||||
/* +h0508 */ AgentEffectsArray party_effects;
|
||||
/* +h0518 */ Array<void *> h0518;
|
||||
/* +h0528 */ GW::Constants::QuestID active_quest_id;
|
||||
/* +h052C */ QuestLog quest_log;
|
||||
/* +h053C */ uint32_t h053C[10];
|
||||
/* +h0564 */ Array<MissionObjective> mission_objectives;
|
||||
/* +h0574 */ Array<uint32_t> henchmen_agent_ids;
|
||||
/* +h0584 */ HeroFlagArray hero_flags;
|
||||
/* +h0594 */ HeroInfoArray hero_info;
|
||||
/* +h05A4 */ Array<void *> cartographed_areas; // Struct size = 0x20
|
||||
/* +h05B4 */ uint32_t h05B4[2];
|
||||
/* +h05BC */ Array<ControlledMinions> controlled_minion_count;
|
||||
/* +h05CC */ Array<uint32_t> missions_completed;
|
||||
/* +h05DC */ Array<uint32_t> missions_bonus;
|
||||
/* +h05EC */ Array<uint32_t> missions_completed_hm;
|
||||
/* +h05FC */ Array<uint32_t> missions_bonus_hm;
|
||||
/* +h060C */ Array<uint32_t> unlocked_map;
|
||||
/* +h061C */ uint32_t h061C[2];
|
||||
/* +h0624 */ PartyMemberMoraleInfo* player_morale_info;
|
||||
/* +h0628 */ uint32_t h028C;
|
||||
/* +h062C */ Array<PartyMoraleLink> party_morale_related;
|
||||
/* +h063C */ uint32_t h063C[16];
|
||||
/* +h067C */ uint32_t player_number;
|
||||
/* +h0680 */ PlayerControlledCharacter* playerControlledChar; // Struct size = 0x134 ?
|
||||
/* +h0684 */ uint32_t is_hard_mode_unlocked;
|
||||
/* +h0688 */ uint32_t h0688[2];
|
||||
/* +h0690 */ uint32_t salvage_session_id;
|
||||
/* +h0694 */ uint32_t h0694[5];
|
||||
/* +h06A8 */ uint32_t playerTeamToken;
|
||||
/* +h06AC */ Array<PetInfo> pets;
|
||||
/* +h06BC */ Array<ProfessionState> party_profession_states; // Current state of primary/secondary/unlocked for current player and party heroes, used in skill window. aka attribStates
|
||||
/* +h06CC */ Array<void *> h06CC;
|
||||
/* +h06DC */ uint32_t h06DC;
|
||||
/* +h06E0 */ Array<void *> h06E0;
|
||||
/* +h06F0 */ SkillbarArray skillbar;
|
||||
/* +h0700 */ Array<uint32_t> learnable_character_skills; // populated at skill trainer and when using signet of capture
|
||||
/* +h0710 */ Array<uint32_t> unlocked_character_skills; // bit field
|
||||
/* +h0720 */ Array<DupeSkill> duplicated_character_skills; // When res signet is bought more than once, its mapped into this array. Used in skill window.
|
||||
/* +h0730 */ Array<void *> h0730;
|
||||
/* +h0740 */ uint32_t experience;
|
||||
/* +h0744 */ uint32_t experience_dupe;
|
||||
/* +h0748 */ uint32_t current_kurzick;
|
||||
/* +h074C */ uint32_t current_kurzick_dupe;
|
||||
/* +h0750 */ uint32_t total_earned_kurzick;
|
||||
/* +h0754 */ uint32_t total_earned_kurzick_dupe;
|
||||
/* +h0758 */ uint32_t current_luxon;
|
||||
/* +h075C */ uint32_t current_luxon_dupe;
|
||||
/* +h0760 */ uint32_t total_earned_luxon;
|
||||
/* +h0764 */ uint32_t total_earned_luxon_dupe;
|
||||
/* +h0768 */ uint32_t current_imperial;
|
||||
/* +h076C */ uint32_t current_imperial_dupe;
|
||||
/* +h0770 */ uint32_t total_earned_imperial;
|
||||
/* +h0774 */ uint32_t total_earned_imperial_dupe;
|
||||
/* +h0778 */ uint32_t unk_faction4;
|
||||
/* +h077C */ uint32_t unk_faction4_dupe;
|
||||
/* +h0780 */ uint32_t unk_faction5;
|
||||
/* +h0784 */ uint32_t unk_faction5_dupe;
|
||||
/* +h0788 */ uint32_t level;
|
||||
/* +h078C */ uint32_t level_dupe;
|
||||
/* +h0790 */ uint32_t morale;
|
||||
/* +h0794 */ uint32_t morale_dupe;
|
||||
/* +h0798 */ uint32_t current_balth;
|
||||
/* +h079C */ uint32_t current_balth_dupe;
|
||||
/* +h07A0 */ uint32_t total_earned_balth;
|
||||
/* +h07A4 */ uint32_t total_earned_balth_dupe;
|
||||
/* +h07A8 */ uint32_t current_skill_points;
|
||||
/* +h07AC */ uint32_t current_skill_points_dupe;
|
||||
/* +h07B0 */ uint32_t total_earned_skill_points;
|
||||
/* +h07B4 */ uint32_t total_earned_skill_points_dupe;
|
||||
/* +h07B8 */ uint32_t max_kurzick;
|
||||
/* +h07BC */ uint32_t max_luxon;
|
||||
/* +h07C0 */ uint32_t max_balth;
|
||||
/* +h07C4 */ uint32_t max_imperial;
|
||||
/* +h07C8 */ uint32_t equipment_status;
|
||||
/* +h07CC */ AgentInfoArray agent_infos;
|
||||
/* +h07DC */ Array<void *> h07DC;
|
||||
/* +h07EC */ MissionMapIconArray mission_map_icons;
|
||||
/* +h07FC */ NPCArray npcs;
|
||||
/* +h080C */ PlayerArray players;
|
||||
/* +h081C */ TitleArray titles;
|
||||
/* +h082C */ Array<TitleTier> title_tiers;
|
||||
/* +h083C */ Array<uint32_t> vanquished_areas;
|
||||
/* +h084C */ uint32_t foes_killed;
|
||||
/* +h0850 */ uint32_t foes_to_kill;
|
||||
//... couple more arrays after this
|
||||
};
|
||||
static_assert(sizeof(WorldContext) == 0x854); // Not the final size of WorldContext, but used to make sure offsets are correct.
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user