├── .editorconfig ├── .github └── workflows │ ├── delete_old_workflow.yml │ ├── pull_requests.yml │ └── release.yml ├── .gitignore ├── .pre-commit-config.yaml ├── AutoHotKeyTrigger ├── AutoHotKeyTrigger.csproj ├── AutoHotKeyTriggerCore.cs ├── AutoHotKeyTriggerSettings.cs ├── FlaskNameToBuff.json ├── JsonDataHelper.cs ├── ProfileManager │ ├── Component │ │ ├── IComponent.cs │ │ └── Wait.cs │ ├── Conditions │ │ ├── AilmentCondition.cs │ │ ├── AnimationCondition.cs │ │ ├── DynamicCondition │ │ │ ├── BuffDictionary.cs │ │ │ ├── DynamicCondition.cs │ │ │ ├── DynamicConditionState.cs │ │ │ ├── FlaskInfo.cs │ │ │ ├── FlasksInfo.cs │ │ │ ├── Interface │ │ │ │ ├── IBuffDictionary.cs │ │ │ │ ├── IDynamicConditionState.cs │ │ │ │ ├── IFlaskInfo.cs │ │ │ │ ├── IFlasksInfo.cs │ │ │ │ ├── IStatusEffect.cs │ │ │ │ ├── IVital.cs │ │ │ │ ├── IVitalsInfo.cs │ │ │ │ └── MonsterRarity.cs │ │ │ ├── NearbyMonsterInfo.cs │ │ │ ├── StatusEffect.cs │ │ │ ├── Vital.cs │ │ │ └── VitalsInfo.cs │ │ ├── FlaskChargesCondition.cs │ │ ├── FlaskEffectCondition.cs │ │ ├── ICondition.cs │ │ ├── StatusEffectCondition.cs │ │ └── VitalsCondition.cs │ ├── Enums │ │ ├── ConditionType.cs │ │ ├── OperatorType.cs │ │ ├── StatusEffectCheckType.cs │ │ └── VitalType.cs │ ├── Profile.cs │ ├── Rule.cs │ └── VirtualKeys.cs └── StatusEffectGroup.json ├── GameHelper ├── Cache │ └── DisappearingEntity.cs ├── Core.cs ├── CoroutineEvents │ ├── GameHelperEvents.cs │ ├── HybridEvents.cs │ └── RemoteEvents.cs ├── GameHelper.csproj ├── GameOverlay.cs ├── GameProcess.cs ├── Plugin │ ├── IPCore.cs │ ├── IPSettings.cs │ ├── PCore.cs │ ├── PManager.cs │ ├── PluginAssemblyLoadContext.cs │ └── PluginMetadata.cs ├── Program.cs ├── RemoteEnums │ ├── Animation.cs │ ├── EntityType.cs │ ├── GameStateTypes.cs │ ├── InventoryName.cs │ └── Rarity.cs ├── RemoteObjects │ ├── AreaChangeCounter.cs │ ├── Components │ │ ├── Actor.cs │ │ ├── Base.cs │ │ ├── Buffs.cs │ │ ├── Charges.cs │ │ ├── Chest.cs │ │ ├── DiesAfterTime.cs │ │ ├── Life.cs │ │ ├── MinimapIcon.cs │ │ ├── NPC.cs │ │ ├── ObjectMagicProperties.cs │ │ ├── Player.cs │ │ ├── Positioned.cs │ │ ├── Render.cs │ │ ├── Shrine.cs │ │ └── TriggerableBlockage.cs │ ├── FilesStructures │ │ └── WorldAreaDat.cs │ ├── GameStates.cs │ ├── GameWindowCull.cs │ ├── GameWindowScale.cs │ ├── LoadedFiles.cs │ ├── RemoteObjectBase.cs │ ├── States │ │ ├── AreaLoadingState.cs │ │ ├── InGameState.cs │ │ └── InGameStateObjects │ │ │ ├── AreaInstance.cs │ │ │ ├── Entity.cs │ │ │ ├── ImportantUiElements.cs │ │ │ ├── Inventory.cs │ │ │ ├── Item.cs │ │ │ ├── ServerData.cs │ │ │ └── WorldData.cs │ ├── TerrainHeightHelper.cs │ └── UiElement │ │ ├── LargeMapUiElement.cs │ │ ├── MapUiElement.cs │ │ └── UiElementBase.cs ├── Settings │ ├── SettingsWindow.cs │ └── State.cs ├── Ui │ ├── DataVisualization.cs │ ├── GameUiExplorer.cs │ ├── OverlayKiller.cs │ └── PerformanceStats.cs ├── Utils │ ├── ImGuiHelper.cs │ ├── JsonHelper.cs │ ├── MathHelper.cs │ ├── MiscHelper.cs │ ├── PatternFinder.cs │ ├── RemoteObjectPropertyDetail.cs │ └── SafeMemoryHandle.cs └── app.manifest ├── GameOffsets ├── GameOffsets.csproj ├── GameProcessName.cs ├── Natives │ ├── StdBucket.cs │ ├── StdList.cs │ ├── StdMap.cs │ ├── StdTuple2D.cs │ ├── StdTuple3D.cs │ ├── StdVector.cs │ ├── StdWString.cs │ └── Util.cs ├── Objects │ ├── AreaChangeOffset.cs │ ├── Components │ │ ├── Actor.cs │ │ ├── Base.cs │ │ ├── Buffs.cs │ │ ├── Charges.cs │ │ ├── Chest.cs │ │ ├── ComponentHeader.cs │ │ ├── Life.cs │ │ ├── ObjectMagicProperties.cs │ │ ├── Player.cs │ │ ├── Positioned.cs │ │ ├── Render.cs │ │ ├── Shrine.cs │ │ └── TriggerableBlockage.cs │ ├── FilesStructures │ │ ├── BaseItemTypesDatOffsets.cs │ │ └── WorldAreaDatOffsets.cs │ ├── GameStateOffsets.cs │ ├── LoadedFilesOffset.cs │ ├── States │ │ ├── AreaLoadingStateOffset.cs │ │ ├── InGameState │ │ │ ├── AreaInstanceOffsets.cs │ │ │ ├── EntityOffsets.cs │ │ │ ├── ImportantUiElementsOffsets.cs │ │ │ ├── InventoryOffset.cs │ │ │ ├── ServerDataOffset.cs │ │ │ └── WorldDataOffset.cs │ │ └── InGameStateOffset.cs │ └── UiElement │ │ ├── MapUiElement.cs │ │ └── UiElementBaseOffset.cs ├── Pattern.cs └── StaticOffsetsPatterns.cs ├── GameOverlay.sln ├── GameOverlay.sln.DotSettings ├── HealthBars ├── Controller │ └── SpriteController.cs ├── HealthBars.cs ├── HealthBars.csproj ├── HealthBarsSettings.cs ├── Sprite.cs ├── SpriteAtlas.cs ├── SpritesheetMetadata.cs ├── View │ ├── Entities │ │ ├── CommonFriendly.cs │ │ ├── CurrentPlayer.cs │ │ ├── Default.cs │ │ ├── Enemy.cs │ │ ├── EntityParams.cs │ │ ├── Friendly.cs │ │ ├── IEntity.cs │ │ └── Invalid.cs │ └── EntityFactory.cs ├── sprites │ ├── ES.png │ ├── EmptyHP.png │ ├── EmptyMana.png │ ├── EnemyHP.png │ ├── HP.png │ ├── Mana.png │ ├── MonsterBar.png │ └── PlayerBars.png ├── spritesheet.json └── spritesheet.png ├── Launcher ├── AutoUpdate.cs ├── GameHelperFinder.cs ├── GameHelperTransformer.cs ├── Launcher.csproj ├── LocationValidator.cs ├── MiscHelper.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── TemporaryFileManager.cs └── app.manifest ├── NuGet.config ├── PreloadAlert ├── PreloadAlert.cs ├── PreloadAlert.csproj └── PreloadSettings.cs ├── README.md ├── Radar ├── Helper.cs ├── IconPicker.cs ├── MapEdgeDetector.cs ├── Radar.cs ├── Radar.csproj ├── RadarSettings.cs └── icons.png └── SamplePluginTemplate └── Changeme ├── Changeme.csproj ├── ChangemeCore.cs └── ChangemeSettings.cs /.github/workflows/delete_old_workflow.yml: -------------------------------------------------------------------------------- 1 | name: DeleteGithubActions 2 | on: 3 | delete: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | workflow_dispatch: 7 | inputs: 8 | workflowName: 9 | description: 'Name of workflow to delete from' 10 | required: true 11 | default: 'DeleteGithubActions' 12 | 13 | jobs: 14 | del_runs: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Delete workflow runs on manual trigger 18 | if: github.event_name=='workflow_dispatch' 19 | uses: mwigginsdev/delete-oldest-workflow-runs@main 20 | with: 21 | token: ${{ github.token }} 22 | repository: ${{ github.repository }} 23 | keep_minimum_runs: '1' 24 | workflow_name: ${{ github.event.inputs.workflowName }} 25 | 26 | - name: Delete workflow runs on manual trigger 27 | if: github.event_name=='schedule' 28 | uses: mwigginsdev/delete-oldest-workflow-runs@main 29 | with: 30 | token: ${{ github.token }} 31 | repository: ${{ github.repository }} 32 | keep_minimum_runs: '1' 33 | workflow_name: 'Release' 34 | 35 | - name: Delete workflow runs on manual trigger 36 | if: github.event_name=='delete' 37 | uses: mwigginsdev/delete-oldest-workflow-runs@main 38 | with: 39 | token: ${{ github.token }} 40 | repository: ${{ github.repository }} 41 | keep_minimum_runs: '5' 42 | workflow_name: 'PullRequest' 43 | -------------------------------------------------------------------------------- /.github/workflows/pull_requests.yml: -------------------------------------------------------------------------------- 1 | name: PullRequest 2 | 3 | on: 4 | pull_request: 5 | branches: [master] 6 | 7 | jobs: 8 | build: 9 | runs-on: ${{ matrix.os }} 10 | strategy: 11 | matrix: 12 | os: [windows-latest] 13 | steps: 14 | - uses: actions/checkout@master 15 | - uses: goit/setup-resharper@v2.0.0 16 | with: 17 | version: '2021.2' 18 | 19 | - name: Setup .NET 20 | uses: actions/setup-dotnet@v1 21 | with: 22 | dotnet-version: 5.0.x 23 | 24 | - name: Restore dependencies 25 | run: dotnet restore 26 | 27 | - name: Resharper Linter 28 | run: InspectCode GameOverlay.sln --build --profile=GameOverlay.sln.DotSettings --output=resharper.html --format=Html 29 | 30 | - name: Upload the Build Artifact 31 | uses: actions/upload-artifact@v2 32 | with: 33 | path: resharper.html 34 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: [master, r/*] 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build: 10 | runs-on: ${{ matrix.os }} 11 | env: 12 | GH_RELEASE_VERSION: ${{ needs.upversion.outputs.new_version }} 13 | needs: [upversion] 14 | strategy: 15 | matrix: 16 | os: [windows-latest] 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: Setup .NET 21 | uses: actions/setup-dotnet@v1 22 | with: 23 | dotnet-version: 5.0.x 24 | 25 | - name: Restore dependencies 26 | run: dotnet restore 27 | 28 | - name: Build 29 | run: | 30 | dotnet build --configuration Release --no-restore 31 | echo ${{ env.GH_RELEASE_VERSION }} > GameHelper/bin/Release/net5.0/VERSION.txt 32 | 33 | - name: Create Zip For Release 34 | uses: papeloto/action-zip@v1 35 | with: 36 | files: GameHelper/bin/Release/net5.0/ 37 | dest: release.zip 38 | 39 | - name: Create Release 40 | uses: softprops/action-gh-release@v1 41 | with: 42 | tag_name: ${{ env.GH_RELEASE_VERSION }} 43 | name: GameHelper-standard-${{ env.GH_RELEASE_VERSION }} 44 | files: release.zip 45 | draft: false 46 | prerelease: false 47 | 48 | upversion: 49 | runs-on: [ubuntu-latest] 50 | outputs: 51 | new_version: ${{ steps.bump-semver.outputs.new_version }} 52 | steps: 53 | - uses: actions/checkout@v2 54 | - uses: actions-ecosystem/action-get-latest-tag@v1 55 | id: get-latest-tag 56 | with: 57 | semver_only: true 58 | - uses: actions-ecosystem/action-bump-semver@v1 59 | id: bump-semver 60 | with: 61 | current_version: ${{ steps.get-latest-tag.outputs.tag }} 62 | level: minor 63 | - uses: actions-ecosystem/action-push-tag@v1 64 | with: 65 | tag: ${{ steps.bump-semver.outputs.new_version }} 66 | message: "${{ steps.bump-semver.outputs.new_version }}: PR #${{ github.event.pull_request.number }} ${{ github.event.pull_request.title }}" 67 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v3.3.0 4 | hooks: 5 | - id: check-yaml 6 | - id: trailing-whitespace 7 | - id: no-commit-to-branch 8 | args: ['--branch', 'master'] 9 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/AutoHotKeyTrigger.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | Library 6 | true 7 | true 8 | x64 9 | 10 | 11 | 12 | 13 | runtime 14 | 15 | 16 | 17 | 18 | 19 | 20 | false 21 | runtime 22 | false 23 | 24 | 25 | 26 | 27 | 28 | PreserveNewest 29 | 30 | 31 | PreserveNewest 32 | 33 | 34 | 35 | 36 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/AutoHotKeyTriggerSettings.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using GameHelper.Plugin; 10 | using ProfileManager; 11 | using ProfileManager.Conditions; 12 | using AutoHotKeyTrigger.ProfileManager.Enums; 13 | 14 | /// 15 | /// plugin settings class. 16 | /// 17 | public sealed class AutoHotKeyTriggerSettings : IPSettings 18 | { 19 | 20 | /// 21 | /// Gets a value indicating whether to enable or disable the auto-quit feature. 22 | /// 23 | public bool EnableAutoQuit = false; 24 | 25 | /// 26 | /// Condition on which user want to auto-quit. 27 | /// 28 | public readonly VitalsCondition AutoQuitCondition = 29 | new(OperatorType.LESS_THAN, VitalType.LIFE_PERCENT, 30); 30 | 31 | /// 32 | /// Gets a key which allows the user to manually quit the game Connection. 33 | /// 34 | public ConsoleKey AutoQuitKey = ConsoleKey.F11; 35 | 36 | /// 37 | /// Gets all the profiles containing rules on when to perform the action. 38 | /// 39 | public readonly Dictionary Profiles = new(); 40 | 41 | /// 42 | /// Gets the currently selected profile. 43 | /// 44 | public string CurrentProfile = string.Empty; 45 | 46 | /// 47 | /// Gets a value indicating weather the debug mode is enabled or not. 48 | /// 49 | public bool DebugMode = false; 50 | 51 | /// 52 | /// Gets a value indicating weather this plugin should work in hideout or not. 53 | /// 54 | public bool ShouldRunInHideout = true; 55 | 56 | /// 57 | /// Gets a value indicating weather user wants to dump the player 58 | /// status effect or not. 59 | /// 60 | public ConsoleKey DumpStatusEffectOnMe = ConsoleKey.F10; 61 | } 62 | } -------------------------------------------------------------------------------- /AutoHotKeyTrigger/JsonDataHelper.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger 6 | { 7 | using System.Collections.Generic; 8 | 9 | /// 10 | /// A helper class that reads JSON data and provides useful functions. 11 | /// 12 | public static class JsonDataHelper 13 | { 14 | /// 15 | /// Gets or sets the flask buff name by looking at flask base name. 16 | /// 17 | public static Dictionary> FlaskNameToBuffGroups { get; set; } = 18 | new(); 19 | 20 | /// 21 | /// Gets or sets the status effects in a group and the group name. 22 | /// 23 | public static Dictionary> StatusEffectGroups { get; set; } = 24 | new(); 25 | } 26 | } -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Component/IComponent.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Component 6 | { 7 | /// 8 | /// A partial condition that can't be used on it's own and 9 | /// adds more logic to a . 10 | /// 11 | public interface IComponent 12 | { 13 | /// 14 | /// Executes the component 15 | /// 16 | /// returns true or false based on the component states 17 | public bool execute(bool isConditionValid); 18 | 19 | /// 20 | /// Display the component via ImGui widgets. 21 | /// 22 | /// should display the component in expanded form or non expanded form. 23 | public void Display(bool expand); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Component/Wait.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | 6 | namespace AutoHotKeyTrigger.ProfileManager.Component 7 | { 8 | using ImGuiNET; 9 | using Newtonsoft.Json; 10 | using System.Diagnostics; 11 | using System.Numerics; 12 | 13 | /// 14 | /// Adds wait to the condition. 15 | /// 16 | public class Wait : IComponent 17 | { 18 | [JsonProperty] private float duration; 19 | private Stopwatch sw; 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | /// duration in seconds to wait for. 25 | public Wait(float duation) 26 | { 27 | this.duration = duation; 28 | this.sw = new(); 29 | } 30 | 31 | /// 32 | public void Display(bool expand) 33 | { 34 | if (expand) 35 | { 36 | ImGui.Text("Condition WAITS for"); 37 | ImGui.SameLine(); 38 | ImGui.DragFloat("(seconds)##WAITCOMPONENT", ref this.duration, 0.05f, 0.0f, 5f); 39 | } 40 | else 41 | { 42 | ImGui.SameLine(); 43 | ImGui.Text("for"); 44 | ImGui.SameLine(); 45 | ImGui.TextColored(new Vector4(255, 255, 0, 255), $"{this.duration}"); 46 | ImGui.SameLine(); 47 | ImGui.Text("seconds."); 48 | } 49 | } 50 | 51 | /// 52 | public bool execute(bool isConditionValid) 53 | { 54 | if (isConditionValid) 55 | { 56 | if (!this.sw.IsRunning) 57 | { 58 | this.sw.Start(); 59 | } 60 | 61 | if (this.sw.ElapsedMilliseconds >= (this.duration * 1000f)) 62 | { 63 | return true; 64 | } 65 | } 66 | else 67 | { 68 | this.sw.Reset(); 69 | } 70 | 71 | return false; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/DynamicCondition/BuffDictionary.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Conditions.DynamicCondition 6 | { 7 | using System.Collections.Generic; 8 | using GameOffsets.Objects.Components; 9 | using Interface; 10 | 11 | /// 12 | /// Describes a set of buffs applied to the player 13 | /// 14 | public class BuffDictionary : IBuffDictionary 15 | { 16 | private readonly IReadOnlyDictionary source; 17 | 18 | /// 19 | /// Creates a new instance 20 | /// 21 | /// Source data for the buffs 22 | public BuffDictionary(IReadOnlyDictionary source) 23 | { 24 | this.source = source; 25 | } 26 | 27 | /// 28 | /// Returns a buff description 29 | /// 30 | /// The buff id 31 | public IStatusEffect this[string id] 32 | { 33 | get 34 | { 35 | if (this.source.TryGetValue(id, out var value)) 36 | { 37 | return new StatusEffect(true, value.TimeLeft, value.TotalTime, value.Charges, value.Effectiveness); 38 | } 39 | 40 | return new StatusEffect(false, 0, 0, 0, 0); 41 | } 42 | } 43 | 44 | /// 45 | /// Checks whether the buff is present 46 | /// 47 | /// The buff id 48 | public bool Has(string id) 49 | { 50 | return this.source.ContainsKey(id); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/DynamicCondition/FlaskInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Conditions.DynamicCondition 6 | { 7 | using System; 8 | using System.Linq; 9 | using GameHelper.RemoteObjects.Components; 10 | using GameHelper.RemoteObjects.States; 11 | using GameHelper.RemoteObjects.States.InGameStateObjects; 12 | using Interface; 13 | 14 | /// 15 | /// The structure describing a flask state 16 | /// 17 | /// Whether the flask effect is active now 18 | /// Current charge amount of a flask 19 | public record FlaskInfo(bool Active, int Charges) : IFlaskInfo 20 | { 21 | /// 22 | /// Create a new instance from the state and flask data 23 | /// 24 | /// State to build the structure from 25 | /// The flask entity 26 | /// 27 | /// 28 | public static FlaskInfo From(InGameState state, Item flaskItem) 29 | { 30 | if (flaskItem.Address == IntPtr.Zero) 31 | { 32 | return new FlaskInfo(false, 0); 33 | } 34 | 35 | var active = false; 36 | if (flaskItem.TryGetComponent(out var @base)) 37 | { 38 | if (!JsonDataHelper.FlaskNameToBuffGroups.TryGetValue(@base.ItemBaseName, out var buffNames)) 39 | { 40 | throw new Exception($"New (IsValid={flaskItem.IsValid}) flask base found " + 41 | $"{@base.ItemBaseName}. Please let the developer know."); 42 | } 43 | 44 | if (state.CurrentAreaInstance.Player.TryGetComponent(out var playerBuffs)) 45 | { 46 | active = buffNames.Any(playerBuffs.StatusEffects.ContainsKey); 47 | } 48 | } 49 | 50 | var charges = flaskItem.TryGetComponent(out var chargesComponent) ? chargesComponent.Current : 0; 51 | return new FlaskInfo(active, charges); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/DynamicCondition/FlasksInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Conditions.DynamicCondition 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using GameHelper.RemoteObjects.States; 11 | using Interface; 12 | 13 | /// 14 | /// Information about a set of flasks 15 | /// 16 | public class FlasksInfo : IFlasksInfo 17 | { 18 | private const int FlaskCount = 5; 19 | 20 | /// 21 | /// Provides access to the flask array 22 | /// 23 | /// The flask index (0-based) 24 | public IFlaskInfo this[int i] 25 | { 26 | get 27 | { 28 | if (i < 0 || i >= FlaskCount) 29 | { 30 | throw new Exception($"Flask index is 0-based and must be in the range of 0-{FlaskCount - 1}"); 31 | } 32 | 33 | return this.flasks[i]; 34 | } 35 | } 36 | 37 | /// 38 | /// The flask in the first slot; 39 | /// 40 | public IFlaskInfo Flask1 => this[0]; 41 | 42 | /// 43 | /// The flask in the second slot; 44 | /// 45 | public IFlaskInfo Flask2 => this[1]; 46 | 47 | /// 48 | /// The flask in the third slot; 49 | /// 50 | public IFlaskInfo Flask3 => this[2]; 51 | 52 | /// 53 | /// The flask in the fourth slot; 54 | /// 55 | public IFlaskInfo Flask4 => this[3]; 56 | 57 | /// 58 | /// The flask in the fifth slot; 59 | /// 60 | public IFlaskInfo Flask5 => this[4]; 61 | 62 | private readonly IReadOnlyList flasks; 63 | 64 | /// 65 | /// Creates a new instance 66 | /// 67 | /// State to build the structure from 68 | public FlasksInfo(InGameState state) 69 | { 70 | this.flasks = Enumerable.Range(0, FlaskCount) 71 | .Select(i => state.CurrentAreaInstance.ServerDataObject.FlaskInventory[0, i]) 72 | .Select(f => FlaskInfo.From(state, f)) 73 | .ToList(); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/DynamicCondition/Interface/IBuffDictionary.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Conditions.DynamicCondition.Interface 6 | { 7 | /// 8 | /// Describes a set of buffs applied to the player 9 | /// 10 | public interface IBuffDictionary 11 | { 12 | /// 13 | /// Returns a buff description 14 | /// 15 | /// The buff id 16 | IStatusEffect this[string id] { get; } 17 | 18 | /// 19 | /// Checks whether the buff is present 20 | /// 21 | bool Has(string id); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/DynamicCondition/Interface/IDynamicConditionState.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Conditions.DynamicCondition.Interface 6 | { 7 | using System.Collections.Generic; 8 | using GameHelper.RemoteEnums; 9 | 10 | /// 11 | /// The structure that can be queried using DynamicCondition 12 | /// 13 | public interface IDynamicConditionState 14 | { 15 | /// 16 | /// The ailment list 17 | /// 18 | IReadOnlyCollection Ailments { get; } 19 | 20 | /// 21 | /// The current animation 22 | /// 23 | Animation Animation { get; } 24 | 25 | /// 26 | /// The buff list 27 | /// 28 | IBuffDictionary Buffs { get; } 29 | 30 | /// 31 | /// The flask information 32 | /// 33 | IFlasksInfo Flasks { get; } 34 | 35 | /// 36 | /// The vitals information 37 | /// 38 | IVitalsInfo Vitals { get; } 39 | 40 | /// 41 | /// Number of friendly nearby monsters 42 | /// 43 | int FriendlyMonsterCount { get; } 44 | 45 | /// 46 | /// Calculates the number of nearby monsters given a rarity selector 47 | /// 48 | /// The rarity selector for monster search 49 | /// 50 | int MonsterCount(MonsterRarity rarity); 51 | 52 | /// 53 | /// Detect a keypress event 54 | /// 55 | bool IsKeyPressedForAction(int vk); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/DynamicCondition/Interface/IFlaskInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Conditions.DynamicCondition.Interface 6 | { 7 | /// 8 | /// The structure describing a flask state 9 | /// 10 | public interface IFlaskInfo 11 | { 12 | /// 13 | /// Whether the flask effect is active now 14 | /// 15 | bool Active { get; init; } 16 | 17 | /// 18 | /// Current charge amount of a flask 19 | /// 20 | int Charges { get; init; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/DynamicCondition/Interface/IFlasksInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Conditions.DynamicCondition.Interface 6 | { 7 | /// 8 | /// Information about a set of flasks 9 | /// 10 | public interface IFlasksInfo 11 | { 12 | /// 13 | /// Provides access to the flask array 14 | /// 15 | /// The flask index (0-based) 16 | IFlaskInfo this[int i] { get; } 17 | 18 | /// 19 | /// The flask in the first slot; 20 | /// 21 | IFlaskInfo Flask1 { get; } 22 | 23 | /// 24 | /// The flask in the second slot; 25 | /// 26 | IFlaskInfo Flask2 { get; } 27 | 28 | /// 29 | /// The flask in the third slot; 30 | /// 31 | IFlaskInfo Flask3 { get; } 32 | 33 | /// 34 | /// The flask in the fourth slot; 35 | /// 36 | IFlaskInfo Flask4 { get; } 37 | 38 | /// 39 | /// The flask in the fifth slot; 40 | /// 41 | IFlaskInfo Flask5 { get; } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/DynamicCondition/Interface/IStatusEffect.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Conditions.DynamicCondition.Interface 6 | { 7 | /// 8 | /// Information about a status effect 9 | /// 10 | public interface IStatusEffect 11 | { 12 | /// 13 | /// Amount of stacks of the effect 14 | /// 15 | int Charges { get; init; } 16 | 17 | /// 18 | /// Whether it exists on the player currently 19 | /// 20 | bool Exists { get; init; } 21 | 22 | /// 23 | /// Time left in percent from total time 24 | /// 25 | double PercentTimeLeft { get; } 26 | 27 | /// 28 | /// Time left in seconds 29 | /// 30 | double TimeLeft { get; init; } 31 | 32 | /// 33 | /// Total time the effect will last 34 | /// 35 | double TotalTime { get; init; } 36 | 37 | /// 38 | /// Effectiveness of the status effect like elusive 39 | /// Value might change from effect to effect and might not be between 0 - 100. 40 | /// 41 | int Effectiveness { get; init; } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/DynamicCondition/Interface/IVital.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Conditions.DynamicCondition.Interface 6 | { 7 | /// 8 | /// Information about a vital 9 | /// 10 | public interface IVital 11 | { 12 | /// 13 | /// Current value 14 | /// 15 | double Current { get; } 16 | 17 | /// 18 | /// Maximum value 19 | /// 20 | double Max { get; } 21 | 22 | /// 23 | /// Value in percent from the max 24 | /// 25 | double Percent { get; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/DynamicCondition/Interface/IVitalsInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Conditions.DynamicCondition.Interface 6 | { 7 | /// 8 | /// Information about player vitals 9 | /// 10 | public interface IVitalsInfo 11 | { 12 | /// 13 | /// Energy shield information 14 | /// 15 | IVital ES { get; } 16 | 17 | /// 18 | /// Health information 19 | /// 20 | IVital HP { get; } 21 | 22 | /// 23 | /// Mana information 24 | /// 25 | IVital Mana { get; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/DynamicCondition/Interface/MonsterRarity.cs: -------------------------------------------------------------------------------- 1 | namespace AutoHotKeyTrigger.ProfileManager.Conditions.DynamicCondition.Interface 2 | { 3 | using System; 4 | 5 | /// 6 | /// different rarity of monster available in the game. 7 | /// 8 | [Flags] 9 | public enum MonsterRarity 10 | { 11 | /// 12 | /// Monsters with red icons (i.e. white monsters). 13 | /// 14 | Normal = 1 << 0, 15 | 16 | /// 17 | /// Monsters with blue icons (i.e. blue monsters). 18 | /// 19 | Magic = 1 << 1, 20 | 21 | /// 22 | /// Monsters with yellow icons (i.e. yellow monsters). 23 | /// 24 | Rare = 1 << 2, 25 | 26 | /// 27 | /// Monsters with big red icon (i.e. golden monsters). 28 | /// 29 | Unique = 1 << 3, 30 | 31 | /// 32 | /// All rarity of monsters. 33 | /// 34 | Any = Normal | Magic | Rare | Unique, 35 | 36 | /// 37 | /// Rare or above. 38 | /// 39 | AtLeastRare = Rare | Unique 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/DynamicCondition/StatusEffect.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Conditions.DynamicCondition 6 | { 7 | using Interface; 8 | 9 | /// 10 | /// Information about a status effect 11 | /// 12 | /// Whether it exists on the player currently 13 | /// Time left in seconds 14 | /// Total time the effect will last 15 | /// Amount of stacks of the effect 16 | /// Effectiveness of effects like elusive. 17 | public record StatusEffect(bool Exists, double TimeLeft, double TotalTime, int Charges, int Effectiveness) : IStatusEffect 18 | { 19 | /// 20 | /// Time left in percent from total time 21 | /// 22 | public double PercentTimeLeft => 23 | this.Exists 24 | ? double.IsPositiveInfinity(this.TimeLeft) 25 | ? 100 26 | : 100 * this.TimeLeft / this.TotalTime 27 | : 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/DynamicCondition/Vital.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Conditions.DynamicCondition 6 | { 7 | using GameOffsets.Objects.Components; 8 | using Interface; 9 | 10 | /// 11 | /// Information about a vital 12 | /// 13 | /// Current value 14 | /// Maximum value 15 | public record Vital(double Current, double Max) : IVital 16 | { 17 | /// 18 | /// Value in percent from the max 19 | /// 20 | public double Percent => this.Current / this.Max * 100; 21 | 22 | /// 23 | /// Creates a new instance 24 | /// 25 | /// Source data for the structure 26 | /// 27 | public static Vital From(VitalStruct vital) 28 | { 29 | return new Vital(vital.Current, vital.Unreserved); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/DynamicCondition/VitalsInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Conditions.DynamicCondition 6 | { 7 | using GameHelper.RemoteObjects.Components; 8 | using Interface; 9 | 10 | /// 11 | /// Information about player vitals 12 | /// 13 | public class VitalsInfo : IVitalsInfo 14 | { 15 | /// 16 | /// Health information 17 | /// 18 | public IVital HP { get; } 19 | 20 | /// 21 | /// Energy shield information 22 | /// 23 | public IVital ES { get; } 24 | 25 | /// 26 | /// Mana information 27 | /// 28 | public IVital Mana { get; } 29 | 30 | /// 31 | /// Creates a new instance 32 | /// 33 | /// Source data for the structure 34 | public VitalsInfo(Life lifeComponent) 35 | { 36 | this.HP = Vital.From(lifeComponent.Health); 37 | this.ES = Vital.From(lifeComponent.EnergyShield); 38 | this.Mana = Vital.From(lifeComponent.Mana); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Conditions/ICondition.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | 6 | namespace AutoHotKeyTrigger.ProfileManager.Conditions 7 | { 8 | using AutoHotKeyTrigger.ProfileManager.Component; 9 | 10 | /// 11 | /// Interface for the conditions on which actions can trigger. 12 | /// 13 | public interface ICondition 14 | { 15 | /// 16 | /// Evaluates the condition. 17 | /// 18 | /// true if the condition is successful, otherwise false. 19 | public bool Evaluate(); 20 | 21 | /// 22 | /// Displays the condition to the user via ImGui. 23 | /// 24 | /// whether to expand the condition or not 25 | public void Display(bool expand); 26 | 27 | /// 28 | /// Adds the component to the condition. 29 | /// 30 | /// component object to add. 31 | void Add(IComponent component); 32 | } 33 | } -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Enums/ConditionType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Enums 6 | { 7 | using Newtonsoft.Json; 8 | using Newtonsoft.Json.Converters; 9 | 10 | /// 11 | /// Conditions supported by this plugin. 12 | /// 13 | [JsonConverter(typeof(StringEnumConverter))] 14 | public enum ConditionType 15 | { 16 | /// 17 | /// Condition based on player Vitals. 18 | /// 19 | VITALS, 20 | 21 | /// 22 | /// Condition based on what player is doing. 23 | /// 24 | ANIMATION, 25 | 26 | /// 27 | /// Condition based on player Buffs/Debuffs. 28 | /// 29 | STATUS_EFFECT, 30 | 31 | /// 32 | /// Condition based on flask mod active on player or not. 33 | /// 34 | FLASK_EFFECT, 35 | 36 | /// 37 | /// Condition based on number of charges flask has. 38 | /// 39 | FLASK_CHARGES, 40 | 41 | /// 42 | /// Condition based on Ailment on the player. 43 | /// 44 | AILMENT, 45 | 46 | /// 47 | /// Condition base on user code 48 | /// 49 | DYNAMIC 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Enums/OperatorType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Enums 6 | { 7 | using Newtonsoft.Json; 8 | using Newtonsoft.Json.Converters; 9 | 10 | /// 11 | /// Different type of operators available to use on the Conditions. 12 | /// 13 | [JsonConverter(typeof(StringEnumConverter))] 14 | public enum OperatorType 15 | { 16 | /// 17 | /// Equal To Operator. 18 | /// 19 | EQUAL_TO, 20 | 21 | /// 22 | /// Not Equal To Operator. 23 | /// 24 | NOT_EQUAL_TO, 25 | 26 | /// 27 | /// Greater Than Operator. 28 | /// 29 | BIGGER_THAN, 30 | 31 | /// 32 | /// Less Than Operator. 33 | /// 34 | LESS_THAN, 35 | 36 | /// 37 | /// List/Dict Contains Operator. 38 | /// 39 | CONTAINS, 40 | 41 | /// 42 | /// List/Dict doesn't Contain Operator. 43 | /// 44 | NOT_CONTAINS 45 | } 46 | } -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Enums/StatusEffectCheckType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Enums 6 | { 7 | using Newtonsoft.Json; 8 | using Newtonsoft.Json.Converters; 9 | 10 | /// 11 | /// Check type for the condition 12 | /// 13 | [JsonConverter(typeof(StringEnumConverter))] 14 | public enum StatusEffectCheckType 15 | { 16 | /// 17 | /// Check remaining buff duration 18 | /// 19 | DURATION, 20 | 21 | /// 22 | /// Check remaning buff duration in percent 23 | /// 24 | DURATION_PERCENT, 25 | 26 | /// 27 | /// Check buff charges 28 | /// 29 | CHARGES 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/ProfileManager/Enums/VitalType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace AutoHotKeyTrigger.ProfileManager.Enums 6 | { 7 | using Newtonsoft.Json; 8 | using Newtonsoft.Json.Converters; 9 | 10 | /// 11 | /// Different type of player Vitals. 12 | /// 13 | [JsonConverter(typeof(StringEnumConverter))] 14 | public enum VitalType 15 | { 16 | /// 17 | /// Condition based on player Mana. 18 | /// 19 | MANA, 20 | 21 | /// 22 | /// Condition based on player Mana. 23 | /// 24 | MANA_PERCENT, 25 | 26 | /// 27 | /// Condition based on player Life. 28 | /// 29 | LIFE, 30 | 31 | /// 32 | /// Condition based on player Life. 33 | /// 34 | LIFE_PERCENT, 35 | 36 | /// 37 | /// Condition based on player Energy Shield. 38 | /// 39 | ENERGYSHIELD, 40 | 41 | /// 42 | /// Condition based on player Energy Shield. 43 | /// 44 | ENERGYSHIELD_PERCENT 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /AutoHotKeyTrigger/StatusEffectGroup.json: -------------------------------------------------------------------------------- 1 | { 2 | "Bleeding Or Corruption": [ 3 | "bleeding", 4 | "puncture", 5 | "puncture_moving", 6 | "physical_damage_and_bleed", 7 | "corrupted_blood", 8 | "corrupted_blood_rain" 9 | ], 10 | "Bleeding": [ 11 | "bleeding", 12 | "puncture", 13 | "puncture_moving", 14 | "physical_damage_and_bleed" 15 | ], 16 | "Corruption": [ 17 | "corrupted_blood", 18 | "corrupted_blood_rain" 19 | ], 20 | "Frozen Or Chilled": [ 21 | "frozen", 22 | "cold_damage_and_freeze", 23 | "chilled", 24 | "ground_ice_chill", 25 | "chilling_bond_in_beam", 26 | "yugul_pool_chilled" 27 | ], 28 | "Frozen": [ 29 | "frozen", 30 | "cold_damage_and_freeze" 31 | ], 32 | "Chilled": [ 33 | "chilled", 34 | "ground_ice_chill", 35 | "chilling_bond_in_beam", 36 | "yugul_pool_chilled" 37 | ], 38 | "Poisoned": [ 39 | "poison", 40 | "viper_strike_orb", 41 | "ground_desecration", 42 | "caustic_cloud", 43 | "chaos_bond_in_beam" 44 | ], 45 | "Burning": [ 46 | "ground_fire_burn", 47 | "ignited", 48 | "searing_bond_in_beam", 49 | "fire_damage_and_ignite", 50 | "righteous_fire_aura", 51 | "demon_righteous_fire_aura" 52 | ], 53 | "Shocked": [ 54 | "shocked", 55 | "ground_lightning_shock", 56 | "seawitch_lightning_beam", 57 | "lightning_damage_and_shock" 58 | ], 59 | "Cursed": [ 60 | "curse_temporal_chains", 61 | "curse_elemental_weakness", 62 | "curse_cold_weakness", 63 | "curse_lightning_weakness", 64 | "curse_chaos_weakness", 65 | "curse_fire_weakness", 66 | "curse_newpunishment", 67 | "curse_enfeeble", 68 | "curse_vulnerability", 69 | "curse_warlords_mark", 70 | "curse_assassins_mark" 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /GameHelper/CoroutineEvents/GameHelperEvents.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.CoroutineEvents 6 | { 7 | using Coroutine; 8 | 9 | /// 10 | /// Co-Routine events specific to the GameHelper. 11 | /// 12 | public static class GameHelperEvents 13 | { 14 | /// 15 | /// Gets the event raised when the game has changed its size, position or both. 16 | /// 17 | public static readonly Event OnMoved = new(); 18 | 19 | /// 20 | /// Gets the event raised when the game Foreground property has changed. 21 | /// 22 | public static readonly Event OnForegroundChanged = new(); 23 | 24 | /// 25 | /// Gets the event raised just before the GameProcess has closed the game. 26 | /// 27 | public static readonly Event OnClose = new(); 28 | 29 | /// 30 | /// To Update data every frame before rendering. 31 | /// 32 | internal static readonly Event PerFrameDataUpdate = new(); 33 | 34 | /// 35 | /// To submit ImGui code for generating the UI. 36 | /// 37 | internal static readonly Event OnRender = new(); 38 | 39 | /// 40 | /// Gets the event raised when GameProcess has opened a new game. 41 | /// 42 | internal static readonly Event OnOpened = new(); 43 | 44 | /// 45 | /// Gets the Game Helper closing event. The event is called whenever 46 | /// all the settings have to be saved. 47 | /// 48 | internal static readonly Event TimeToSaveAllSettings = new(); 49 | } 50 | } -------------------------------------------------------------------------------- /GameHelper/CoroutineEvents/HybridEvents.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.CoroutineEvents 6 | { 7 | using Coroutine; 8 | 9 | /// 10 | /// Events specific to the Game and the GameHelper state. 11 | /// 12 | public static class HybridEvents 13 | { 14 | /// 15 | /// Gets the event that is triggered after all the preloads 16 | /// of the current area/zone are updated. 17 | /// 18 | public static readonly Event PreloadsUpdated = new(); 19 | } 20 | } -------------------------------------------------------------------------------- /GameHelper/CoroutineEvents/RemoteEvents.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.CoroutineEvents 6 | { 7 | using Coroutine; 8 | 9 | /// 10 | /// Co-Routine events specific to the game. 11 | /// 12 | public static class RemoteEvents 13 | { 14 | /// 15 | /// Gets the event that is triggered 50ms after the area change detection. 16 | /// Area change is detected by checking if the time spend on the 17 | /// loading screen (given to us by the game) is greater than the 18 | /// last recorded time and IsLoading bool is set to false. 19 | /// NOTE: when this is triggered the preloads might not be up to date. 20 | /// 21 | public static readonly Event AreaChanged = new(); 22 | 23 | /// 24 | /// Gets the Current State Changed event. 25 | /// 26 | internal static readonly Event StateChanged = new(); 27 | } 28 | } -------------------------------------------------------------------------------- /GameHelper/GameHelper.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | GameHelper.Program 6 | app.manifest 7 | zaafar 8 | An overlay to help play the game. 9 | true 10 | 11 | 12 | 13 | Exe 14 | false 15 | ;NU1605 16 | 1701;1702; 1591 17 | x64 18 | 19 | 20 | 21 | WinExe 22 | x64 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /GameHelper/Plugin/IPCore.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.Plugin 6 | { 7 | /// 8 | /// Interface for creating plugins. 9 | /// 10 | internal interface IPCore 11 | { 12 | /// 13 | /// Called at the init of the plugin to set 14 | /// it's directory information. 15 | /// 16 | /// plugin dll directory. 17 | public void SetPluginDllLocation(string dllLocation); 18 | 19 | /// 20 | /// Called when the plugin is enabled by the user or when GameOverlay 21 | /// starts and plugin is already enabled. 22 | /// 23 | /// value indicating whether game is open or not. 24 | public void OnEnable(bool isGameOpened); 25 | 26 | /// 27 | /// Called when the plugin is disabled by the user. 28 | /// 29 | public void OnDisable(); 30 | 31 | /// 32 | /// Called to draw the plugin settings on the GameHelper Settings window. 33 | /// Should use ImGui objects to draw the settings. 34 | /// 35 | public void DrawSettings(); 36 | 37 | /// 38 | /// Draws the plugin UI. This function isn't called when the plugin is disabled. 39 | /// 40 | public void DrawUI(); 41 | 42 | /// 43 | /// Called when it's time to save all the settings 44 | /// related to the plugin on the file. 45 | /// NOTE: Load settings function isn't provided as 46 | /// it's expected the plugin will load the settings 47 | /// in OnEnable function. 48 | /// 49 | public void SaveSettings(); 50 | } 51 | } -------------------------------------------------------------------------------- /GameHelper/Plugin/IPSettings.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.Plugin 6 | { 7 | /// 8 | /// Interface for loading/saving plugin settings. 9 | /// 10 | public interface IPSettings { } 11 | } -------------------------------------------------------------------------------- /GameHelper/Plugin/PCore.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.Plugin 6 | { 7 | /// 8 | /// Interface for creating plugins. 9 | /// 10 | /// plugin's setting class name. 11 | public abstract class PCore : IPCore 12 | where TSettings : IPSettings, new() 13 | { 14 | /// 15 | /// Gets or sets the plugin root directory folder. 16 | /// 17 | public string DllDirectory; 18 | 19 | /// 20 | /// Gets or sets the plugin settings. 21 | /// 22 | public TSettings Settings = new(); 23 | 24 | /// 25 | public abstract void OnDisable(); 26 | 27 | /// 28 | public abstract void OnEnable(bool isGameOpened); 29 | 30 | /// 31 | public abstract void DrawSettings(); 32 | 33 | /// 34 | public abstract void DrawUI(); 35 | 36 | /// 37 | public abstract void SaveSettings(); 38 | 39 | /// 40 | public void SetPluginDllLocation(string dllLocation) 41 | { 42 | this.DllDirectory = dllLocation; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /GameHelper/Plugin/PluginAssemblyLoadContext.cs: -------------------------------------------------------------------------------- 1 | namespace GameHelper.Plugin 2 | { 3 | using System.Reflection; 4 | using System.Runtime.Loader; 5 | 6 | internal class PluginAssemblyLoadContext : AssemblyLoadContext 7 | { 8 | private readonly AssemblyDependencyResolver resolver; 9 | 10 | public PluginAssemblyLoadContext(string assemblyLocation) 11 | { 12 | this.resolver = new AssemblyDependencyResolver(assemblyLocation); 13 | } 14 | 15 | protected override Assembly Load(AssemblyName assemblyName) 16 | { 17 | var path = this.resolver.ResolveAssemblyToPath(assemblyName); 18 | if (path != null) 19 | { 20 | return this.LoadFromAssemblyPath(path); 21 | } 22 | 23 | return null; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /GameHelper/Plugin/PluginMetadata.cs: -------------------------------------------------------------------------------- 1 | namespace GameHelper.Plugin 2 | { 3 | /// 4 | /// Container for plugin metadata. 5 | /// 6 | internal class PluginMetadata 7 | { 8 | /// 9 | /// Gets or sets a value indicating whether the plugin is enabled or not. 10 | /// 11 | public bool Enable { get; set; } = true; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /GameHelper/Program.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper 6 | { 7 | using System; 8 | using System.IO; 9 | using System.Threading.Tasks; 10 | using Utils; 11 | 12 | /// 13 | /// Class executed when the application starts. 14 | /// 15 | internal class Program 16 | { 17 | /// 18 | /// function executed when the application starts. 19 | /// 20 | private static async Task Main() 21 | { 22 | AppDomain.CurrentDomain.UnhandledException += (sender, exceptionArgs) => 23 | { 24 | var errorText = "Program exited with message:\n " + exceptionArgs.ExceptionObject; 25 | File.AppendAllText("Error.log", $"{DateTime.Now:g} {errorText}\r\n{new string('-', 30)}\r\n"); 26 | Environment.Exit(1); 27 | }; 28 | 29 | using (Core.Overlay = new GameOverlay(MiscHelper.GenerateRandomString())) 30 | { 31 | await Core.Overlay.Run(); 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /GameHelper/RemoteEnums/GameStateTypes.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteEnums 6 | { 7 | /// 8 | /// Gets all known states of the game. 9 | /// 10 | public enum GameStateTypes 11 | { 12 | /// 13 | /// When user is on the Area Loading Screen. 14 | /// 15 | AreaLoadingState, 16 | 17 | /// 18 | /// Game State. 19 | /// 20 | ChangePasswordState, 21 | 22 | /// 23 | /// When user is viewing the credit screen window (accessable from login screen) 24 | /// 25 | CreditsState, 26 | 27 | /// 28 | /// When user has opened the escape menu. 29 | /// 30 | EscapeState, 31 | 32 | /// 33 | /// When User is in Town/Hideout/Area/Zone etc. 34 | /// 35 | InGameState, 36 | 37 | /// 38 | /// The user is watching the GGG animation that comes before the login screen. 39 | /// 40 | PreGameState, 41 | 42 | /// 43 | /// When user is on the Login screen. 44 | /// 45 | LoginState, 46 | 47 | /// 48 | /// When user is transitioning from to . 49 | /// 50 | WaitingState, 51 | 52 | /// 53 | /// When user is on the create new character screen. 54 | /// 55 | CreateCharacterState, 56 | 57 | /// 58 | /// When user is on the select character screen. 59 | /// 60 | SelectCharacterState, 61 | 62 | /// 63 | /// When user is on the delete character screen. 64 | /// 65 | DeleteCharacterState, 66 | 67 | /// 68 | /// When user is transitioning from to . 69 | /// 70 | LoadingState, 71 | 72 | /// 73 | /// This is a special State, changing to this state will not trigger State Change Event. 74 | /// This is just for displaying purposes. It means Game isn't stared. 75 | /// 76 | GameNotLoaded 77 | } 78 | } -------------------------------------------------------------------------------- /GameHelper/RemoteEnums/InventoryName.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteEnums 6 | { 7 | /// 8 | /// Read Inventories.dat file for inventory name and index mapping. 9 | /// Remember, in the game, inventory index starts from 0x01. 10 | /// In the Inventories.dat file, inventory index starts from 0x00. 11 | /// 12 | public enum InventoryName 13 | { 14 | #pragma warning disable CS1591, SA1602 15 | NoInvSelected, 16 | MainInventory1, 17 | BodyArmour1, 18 | Weapon1, 19 | Offhand1, 20 | Helm1, 21 | Amulet1, 22 | Ring1, 23 | Ring2, 24 | Gloves1, 25 | Boots1, 26 | Belt1, 27 | Flask1, 28 | Cursor1, 29 | Map1, 30 | Weapon2, 31 | Offhand2, 32 | StrMasterCrafting, 33 | StrDexMasterCrafting, 34 | DexMasterCrafting, 35 | DexIntMasterCrafting, 36 | IntMasterCrafting, 37 | StrIntMasterCrafting, 38 | PVPMasterCrafting, 39 | PassiveJewels1, 40 | AnimatedArmour1, 41 | GuildTag1, 42 | StashInventoryId, 43 | DivinationCardTrade, 44 | Darkshrine, 45 | TalismanTrade, 46 | Leaguestone1, 47 | BestiaryCrafting, 48 | IncursionSacrifice, 49 | BetrayalUnveiling, 50 | ItemSynthesisInput, 51 | ItemSynthesisOutput, 52 | BlightCraftingInput, 53 | BlightCraftingItem, 54 | MetamorphosisGenomeInput, 55 | AtlasUpgrades1, 56 | AtlasUpgradesStorage, 57 | ExpeditionMapMission, 58 | ExpeditionDeal1, 59 | HarvestCraftingItem, 60 | HeistContractMission, 61 | HeistNpcEquipment1, 62 | HeistNpcEquipment2, 63 | HeistNpcEquipment3, 64 | HeistNpcEquipment4, 65 | HeistNpcEquipment5, 66 | HeistNpcEquipment6, 67 | HeistNpcEquipment7, 68 | HeistNpcEquipment8, 69 | HeistNpcEquipment9, 70 | Trinket1, 71 | HeistBlueprintMission, 72 | HeistStorage1, 73 | RitualSavedRewards1, 74 | DONOTUSE1, 75 | DONOTUSE2, 76 | DONOTUSE3, 77 | DONOTUSE4, 78 | RESERVED1, 79 | RESERVED2, 80 | RESERVED3, 81 | RESERVED4, 82 | UltimatumCraftingItem, 83 | RESERVED5, 84 | RESERVED6, 85 | ExpeditionStorage1, 86 | HellscapeModificationInventory1, 87 | LabyrinthCraftingInput, 88 | SentinelDroneInventory1, 89 | SentinelStorage1, 90 | LakeTabletInventory1, 91 | MemoryLineMaps 92 | #pragma warning restore CS1591, SA1602 93 | } 94 | } -------------------------------------------------------------------------------- /GameHelper/RemoteEnums/Rarity.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteEnums 6 | { 7 | /// 8 | /// Read Rarity.dat file for Rarity to integer mapping. 9 | /// 10 | public enum Rarity 11 | { 12 | /// 13 | /// Normal Item/Monster. 14 | /// 15 | Normal, 16 | 17 | /// 18 | /// Magic Item/Monster. 19 | /// 20 | Magic, 21 | 22 | /// 23 | /// Rare Item/Monster. 24 | /// 25 | Rare, 26 | 27 | /// 28 | /// Unique Item/Monster. 29 | /// 30 | Unique 31 | } 32 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/AreaChangeCounter.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using Coroutine; 10 | using CoroutineEvents; 11 | using GameOffsets.Objects; 12 | using ImGuiNET; 13 | 14 | /// 15 | /// Points to the AreaChangeCounter object and read/cache it's value 16 | /// on every area change. 17 | /// 18 | public class AreaChangeCounter : RemoteObjectBase 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | /// address of the remote memory object. 24 | internal AreaChangeCounter(IntPtr address) 25 | : base(address) 26 | { 27 | CoroutineHandler.Start(this.OnAreaChange(), priority: int.MaxValue); 28 | } 29 | 30 | /// 31 | /// Gets the cached value of the AreaChangeCounter. 32 | /// 33 | public int Value { get; private set; } = int.MaxValue; 34 | 35 | /// 36 | /// Converts the class data to ImGui. 37 | /// 38 | internal override void ToImGui() 39 | { 40 | base.ToImGui(); 41 | ImGui.Text($"Area Change Counter: {this.Value}"); 42 | } 43 | 44 | /// 45 | protected override void CleanUpData() 46 | { 47 | this.Value = int.MaxValue; 48 | } 49 | 50 | /// 51 | protected override void UpdateData(bool hasAddressChanged) 52 | { 53 | var reader = Core.Process.Handle; 54 | this.Value = reader.ReadMemory(this.Address).counter; 55 | } 56 | 57 | private IEnumerator OnAreaChange() 58 | { 59 | while (true) 60 | { 61 | yield return new Wait(RemoteEvents.AreaChanged); 62 | if (this.Address != IntPtr.Zero) 63 | { 64 | this.UpdateData(false); 65 | } 66 | } 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/Components/Actor.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.Components 6 | { 7 | using System; 8 | using GameOffsets.Objects.Components; 9 | using ImGuiNET; 10 | using RemoteEnums; 11 | 12 | /// 13 | /// The component in the entity. 14 | /// 15 | public class Actor : RemoteObjectBase 16 | { 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// address of the component. 21 | public Actor(IntPtr address) 22 | : base(address, true) { } 23 | 24 | /// 25 | /// Gets a value indicating what the player is doing. 26 | /// 27 | public Animation Animation { get; private set; } = Animation.Idle; 28 | 29 | /// 30 | /// Converts the class data to ImGui. 31 | /// 32 | internal override void ToImGui() 33 | { 34 | base.ToImGui(); 35 | ImGui.Text($"AnimationId: {(int)this.Animation}, Animation: {this.Animation}"); 36 | } 37 | 38 | /// 39 | protected override void CleanUpData() 40 | { 41 | throw new Exception("Component Address should never be Zero."); 42 | } 43 | 44 | /// 45 | protected override void UpdateData(bool hasAddressChanged) 46 | { 47 | var reader = Core.Process.Handle; 48 | var data = reader.ReadMemory(this.Address); 49 | this.Animation = (Animation)data.AnimationId; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/Components/Base.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.Components 6 | { 7 | using System; 8 | using System.Collections.Concurrent; 9 | using System.Collections.Generic; 10 | using Coroutine; 11 | using GameOffsets.Objects.Components; 12 | using GameOffsets.Objects.FilesStructures; 13 | using ImGuiNET; 14 | 15 | /// 16 | /// The component in the entity. 17 | /// 18 | public class Base : RemoteObjectBase 19 | { 20 | /// 21 | /// Cache the BaseItemType.Dat data to save few reads per frame. 22 | /// 23 | private static readonly ConcurrentDictionary BaseItemTypeDatCache = new(); 24 | 25 | /// 26 | /// Initializes a new instance of the class. 27 | /// 28 | /// address of the component. 29 | public Base(IntPtr address) 30 | : base(address, true) { } 31 | 32 | static Base() 33 | { 34 | CoroutineHandler.Start(OnGameClose()); 35 | } 36 | 37 | /// 38 | /// Gets the items base name. 39 | /// 40 | public string ItemBaseName { get; private set; } = string.Empty; 41 | 42 | /// 43 | internal override void ToImGui() 44 | { 45 | base.ToImGui(); 46 | ImGui.Text($"Base Name: {this.ItemBaseName}"); 47 | } 48 | 49 | /// 50 | protected override void CleanUpData() 51 | { 52 | throw new Exception("Component Address should never be Zero."); 53 | } 54 | 55 | /// 56 | protected override void UpdateData(bool hasAddressChanged) 57 | { 58 | var reader = Core.Process.Handle; 59 | var data = reader.ReadMemory(this.Address); 60 | if (BaseItemTypeDatCache.TryGetValue(data.BaseInternalPtr, out var itemName)) 61 | { 62 | this.ItemBaseName = itemName; 63 | } 64 | else 65 | { 66 | var baseItemTypeDatRow = reader.ReadMemory(data.BaseInternalPtr); 67 | var name = reader.ReadStdWString(baseItemTypeDatRow.BaseNamePtr); 68 | if (!string.IsNullOrEmpty(name)) 69 | { 70 | BaseItemTypeDatCache[data.BaseInternalPtr] = name; 71 | this.ItemBaseName = name; 72 | } 73 | } 74 | } 75 | 76 | private static IEnumerable OnGameClose() 77 | { 78 | while (true) 79 | { 80 | yield return new(CoroutineEvents.GameHelperEvents.OnClose); 81 | BaseItemTypeDatCache.Clear(); 82 | } 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/Components/Charges.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.Components 6 | { 7 | using System; 8 | using GameOffsets.Objects.Components; 9 | using ImGuiNET; 10 | 11 | /// 12 | /// The component in the entity. 13 | /// 14 | public class Charges : RemoteObjectBase 15 | { 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | /// address of the component. 20 | public Charges(IntPtr address) 21 | : base(address, true) { } 22 | 23 | /// 24 | /// Gets a value indicating number of charges the flask has. 25 | /// 26 | public int Current { get; private set; } 27 | 28 | /// 29 | /// Converts the class data to ImGui. 30 | /// 31 | internal override void ToImGui() 32 | { 33 | base.ToImGui(); 34 | ImGui.Text($"Current Charges: {this.Current}"); 35 | } 36 | 37 | /// 38 | protected override void CleanUpData() 39 | { 40 | throw new Exception("Component Address should never be Zero."); 41 | } 42 | 43 | /// 44 | protected override void UpdateData(bool hasAddressChanged) 45 | { 46 | var reader = Core.Process.Handle; 47 | var data = reader.ReadMemory(this.Address); 48 | this.Current = data.current; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/Components/Chest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.Components 6 | { 7 | using System; 8 | using GameOffsets.Objects.Components; 9 | using ImGuiNET; 10 | 11 | /// 12 | /// The component in the entity. 13 | /// 14 | public class Chest : RemoteObjectBase 15 | { 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | /// address of the component. 20 | public Chest(IntPtr address) 21 | : base(address, true) { } 22 | 23 | /// 24 | /// Gets a value indicating whether chest is opened or not. 25 | /// 26 | public bool IsOpened { get; private set; } 27 | 28 | /// 29 | /// Gets a value indicating whether chest is a strongbox or not. 30 | /// 31 | public bool IsStrongbox { get; private set; } 32 | 33 | /// 34 | /// Gets a value indicating whether chest label is visible or not 35 | /// NOTE: Breach chests, Legion chests, Normal Chests labels are visible. 36 | /// 37 | public bool IsLabelVisible { get; private set; } 38 | 39 | /// 40 | /// Converts the class data to ImGui. 41 | /// 42 | internal override void ToImGui() 43 | { 44 | base.ToImGui(); 45 | ImGui.Text($"IsOpened: {this.IsOpened}"); 46 | ImGui.Text($"IsStrongbox: {this.IsStrongbox}"); 47 | ImGui.Text($"IsLabelVisible: {this.IsLabelVisible}"); 48 | } 49 | 50 | /// 51 | protected override void CleanUpData() 52 | { 53 | throw new Exception("Component Address should never be Zero."); 54 | } 55 | 56 | /// 57 | protected override void UpdateData(bool hasAddressChanged) 58 | { 59 | var reader = Core.Process.Handle; 60 | var data = reader.ReadMemory(this.Address); 61 | this.IsOpened = data.IsOpened; 62 | if (hasAddressChanged) 63 | { 64 | var dataInternal = reader.ReadMemory(data.ChestsDataPtr); 65 | this.IsStrongbox = dataInternal.StrongboxDatPtr != IntPtr.Zero; 66 | this.IsLabelVisible = dataInternal.IsLabelVisible; 67 | } 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/Components/DiesAfterTime.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.Components 6 | { 7 | using System; 8 | 9 | /// 10 | /// The component in the entity. 11 | /// 12 | public class DiesAfterTime : RemoteObjectBase 13 | { 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | /// address of the component. 18 | public DiesAfterTime(IntPtr address) 19 | : base(address, true) { } 20 | 21 | /// 22 | protected override void CleanUpData() 23 | { 24 | throw new Exception("Component Address should never be Zero."); 25 | } 26 | 27 | /// 28 | protected override void UpdateData(bool hasAddressChanged) { } 29 | } 30 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/Components/Life.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.Components 6 | { 7 | using System; 8 | using GameOffsets.Objects.Components; 9 | using ImGuiNET; 10 | using Utils; 11 | 12 | /// 13 | /// The component in the entity. 14 | /// 15 | public class Life : RemoteObjectBase 16 | { 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// address of the component. 21 | public Life(IntPtr address) 22 | : base(address, true) { } 23 | 24 | /// 25 | /// Gets a value indicating whether the entity is alive or not. 26 | /// 27 | public bool IsAlive { get; private set; } = true; 28 | 29 | /// 30 | /// Gets the health related information of the entity. 31 | /// 32 | public VitalStruct Health { get; private set; } 33 | 34 | /// 35 | /// Gets the energyshield related information of the entity. 36 | /// 37 | public VitalStruct EnergyShield { get; private set; } 38 | 39 | /// 40 | /// Gets the mana related information of the entity. 41 | /// 42 | public VitalStruct Mana { get; private set; } 43 | 44 | /// 45 | /// Converts the class data to ImGui. 46 | /// 47 | internal override void ToImGui() 48 | { 49 | base.ToImGui(); 50 | 51 | if (ImGui.TreeNode("Health")) 52 | { 53 | this.VitalToImGui(this.Health); 54 | ImGui.TreePop(); 55 | } 56 | 57 | if (ImGui.TreeNode("Energy Shield")) 58 | { 59 | this.VitalToImGui(this.EnergyShield); 60 | ImGui.TreePop(); 61 | } 62 | 63 | if (ImGui.TreeNode("Mana")) 64 | { 65 | this.VitalToImGui(this.Mana); 66 | ImGui.TreePop(); 67 | } 68 | } 69 | 70 | /// 71 | protected override void CleanUpData() 72 | { 73 | throw new Exception("Component Address should never be Zero."); 74 | } 75 | 76 | /// 77 | protected override void UpdateData(bool hasAddressChanged) 78 | { 79 | var reader = Core.Process.Handle; 80 | var data = reader.ReadMemory(this.Address); 81 | this.Health = data.Health; 82 | this.EnergyShield = data.EnergyShield; 83 | this.Mana = data.Mana; 84 | this.IsAlive = data.Health.Current > 0; 85 | } 86 | 87 | private void VitalToImGui(VitalStruct data) 88 | { 89 | ImGuiHelper.IntPtrToImGui("PtrToSelf", data.PtrToLifeComponent); 90 | ImGui.Text($"Regeneration: {data.Regeneration}"); 91 | ImGui.Text($"Total: {data.Total}"); 92 | ImGui.Text($"ReservedFlat: {data.ReservedFlat}"); 93 | ImGui.Text($"Current: {data.Current}"); 94 | ImGui.Text($"Reserved(%%): {data.ReservedPercent}"); 95 | ImGui.Text($"Current(%%): {data.CurrentInPercent()}"); 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/Components/MinimapIcon.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.Components 6 | { 7 | using System; 8 | 9 | /// 10 | /// The component in the entity. 11 | /// 12 | public class MinimapIcon : RemoteObjectBase 13 | { 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | /// address of the component. 18 | public MinimapIcon(IntPtr address) 19 | : base(address, true) { } 20 | 21 | /// 22 | protected override void CleanUpData() 23 | { 24 | throw new Exception("Component Address should never be Zero."); 25 | } 26 | 27 | /// 28 | protected override void UpdateData(bool hasAddressChanged) { } 29 | } 30 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/Components/NPC.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.Components 6 | { 7 | using System; 8 | 9 | /// 10 | /// The component in the entity. 11 | /// 12 | public class NPC : RemoteObjectBase 13 | { 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | /// address of the component. 18 | public NPC(IntPtr address) 19 | : base(address, true) { } 20 | 21 | /// 22 | protected override void CleanUpData() 23 | { 24 | throw new Exception("Component Address should never be Zero."); 25 | } 26 | 27 | /// 28 | protected override void UpdateData(bool hasAddressChanged) { } 29 | } 30 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/Components/ObjectMagicProperties.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.Components 6 | { 7 | using System; 8 | using GameOffsets.Objects.Components; 9 | using ImGuiNET; 10 | using RemoteEnums; 11 | 12 | /// 13 | /// ObjectMagicProperties component of the entity. 14 | /// 15 | public class ObjectMagicProperties : RemoteObjectBase 16 | { 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// address of the component. 21 | public ObjectMagicProperties(IntPtr address) 22 | : base(address, true) { } 23 | 24 | /// 25 | /// Gets a value indicating entity rarity information. 26 | /// 27 | public Rarity Rarity { get; private set; } = Rarity.Normal; 28 | 29 | /// 30 | /// Converts the class data to ImGui. 31 | /// 32 | internal override void ToImGui() 33 | { 34 | base.ToImGui(); 35 | ImGui.Text($"Rarity: {this.Rarity}"); 36 | } 37 | 38 | /// 39 | protected override void CleanUpData() 40 | { 41 | throw new Exception("Component Address should never be Zero."); 42 | } 43 | 44 | /// 45 | protected override void UpdateData(bool hasAddressChanged) 46 | { 47 | if (hasAddressChanged) 48 | { 49 | var reader = Core.Process.Handle; 50 | var data = reader.ReadMemory(this.Address); 51 | this.Rarity = (Rarity)data.Rarity; 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/Components/Player.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.Components 6 | { 7 | using System; 8 | using GameOffsets.Objects.Components; 9 | using ImGuiNET; 10 | 11 | /// 12 | /// The component in the entity. 13 | /// 14 | public class Player : RemoteObjectBase 15 | { 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | /// address of the component. 20 | public Player(IntPtr address) 21 | : base(address, true) { } 22 | 23 | /// 24 | /// Gets the name of the player. 25 | /// 26 | public string Name { get; private set; } 27 | 28 | /// 29 | /// Converts the class data to ImGui. 30 | /// 31 | internal override void ToImGui() 32 | { 33 | base.ToImGui(); 34 | ImGui.Text($"Player Name: {this.Name}"); 35 | } 36 | 37 | /// 38 | protected override void CleanUpData() 39 | { 40 | throw new Exception("Component Address should never be Zero."); 41 | } 42 | 43 | /// 44 | protected override void UpdateData(bool hasAddressChanged) 45 | { 46 | if (!hasAddressChanged) 47 | { 48 | return; 49 | } 50 | 51 | var reader = Core.Process.Handle; 52 | var data = reader.ReadMemory(this.Address); 53 | this.Name = reader.ReadStdWString(data.Name); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/Components/Positioned.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.Components 6 | { 7 | using System; 8 | using GameOffsets.Objects.Components; 9 | using GameOffsets.Objects.States.InGameState; 10 | using ImGuiNET; 11 | 12 | /// 13 | /// The component in the entity. 14 | /// 15 | public class Positioned : RemoteObjectBase 16 | { 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// address of the component. 21 | public Positioned(IntPtr address) 22 | : base(address, true) { } 23 | 24 | /// 25 | /// Gets the flags related to the entity from the positioned component. 26 | /// NOTE: This flag contains the information if the entity is friendly or not. 27 | /// 28 | public byte Flags { get; private set; } 29 | 30 | /// 31 | /// Gets a value indicating whether the entity is friendly or not. 32 | /// 33 | public bool IsFriendly { get; private set; } 34 | 35 | /// 36 | /// Converts the class data to ImGui. 37 | /// 38 | internal override void ToImGui() 39 | { 40 | base.ToImGui(); 41 | ImGui.Text($"Flags: {this.Flags:X}"); 42 | ImGui.Text($"IsFriendly: {this.IsFriendly}"); 43 | } 44 | 45 | /// 46 | protected override void UpdateData(bool hasAddressChanged) 47 | { 48 | var reader = Core.Process.Handle; 49 | var data = reader.ReadMemory(this.Address); 50 | this.Flags = data.Reaction; 51 | this.IsFriendly = EntityHelper.IsFriendly(data.Reaction); 52 | } 53 | 54 | /// 55 | protected override void CleanUpData() 56 | { 57 | throw new Exception("Component Address should never be Zero."); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/Components/Render.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.Components 6 | { 7 | using System; 8 | using GameOffsets.Natives; 9 | using GameOffsets.Objects.Components; 10 | using GameOffsets.Objects.States.InGameState; 11 | using ImGuiNET; 12 | 13 | /// 14 | /// The component in the entity. 15 | /// 16 | public class Render : RemoteObjectBase 17 | { 18 | private static readonly float WorldToGridRatio = 19 | TileStructure.TileToWorldConversion / TileStructure.TileToGridConversion; 20 | 21 | private StdTuple3D gridPos2D; 22 | 23 | /// 24 | /// Initializes a new instance of the class. 25 | /// 26 | /// address of the component. 27 | public Render(IntPtr address) 28 | : base(address, true) { } 29 | 30 | /// 31 | /// Gets the position where entity is located on the grid (map). 32 | /// 33 | public StdTuple3D GridPosition 34 | { 35 | get => this.gridPos2D; 36 | private set => this.gridPos2D = value; 37 | } 38 | 39 | /// 40 | /// Gets the position where entity is located on the grid (map). 41 | /// 42 | public StdTuple3D ModelBounds { get; private set; } 43 | 44 | /// 45 | /// Gets the postion where entity is rendered in the game world. 46 | /// NOTE: Z-Axis is pointing to the (visible/invisible) healthbar. 47 | /// 48 | public StdTuple3D WorldPosition { get; private set; } 49 | 50 | /// 51 | /// Gets the terrain height on which the Entity is standing. 52 | /// 53 | public float TerrainHeight { get; private set; } 54 | 55 | /// 56 | /// Converts the class data to ImGui. 57 | /// 58 | internal override void ToImGui() 59 | { 60 | base.ToImGui(); 61 | ImGui.Text($"Grid Position: {this.gridPos2D}"); 62 | ImGui.Text($"World Position: {this.WorldPosition}"); 63 | ImGui.Text($"Terrain Height (Z-Axis): {this.TerrainHeight}"); 64 | ImGui.Text($"Model Bounds: {this.ModelBounds}"); 65 | } 66 | 67 | /// 68 | protected override void CleanUpData() 69 | { 70 | throw new Exception("Component Address should never be Zero."); 71 | } 72 | 73 | /// 74 | protected override void UpdateData(bool hasAddressChanged) 75 | { 76 | var reader = Core.Process.Handle; 77 | var data = reader.ReadMemory(this.Address); 78 | this.WorldPosition = data.CurrentWorldPosition; 79 | this.ModelBounds = data.CharactorModelBounds; 80 | this.TerrainHeight = (float)Math.Round(data.TerrainHeight, 4); 81 | this.gridPos2D.X = data.CurrentWorldPosition.X / WorldToGridRatio; 82 | this.gridPos2D.Y = data.CurrentWorldPosition.Y / WorldToGridRatio; 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/Components/Shrine.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.Components 6 | { 7 | using System; 8 | using GameOffsets.Objects.Components; 9 | using ImGuiNET; 10 | 11 | /// 12 | /// The component in the entity. 13 | /// 14 | public class Shrine : RemoteObjectBase 15 | { 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | /// address of the component. 20 | public Shrine(IntPtr address) 21 | : base(address, true) { } 22 | 23 | /// 24 | /// Gets a value indicating whether chest is opened or not. 25 | /// 26 | public bool IsUsed { get; private set; } 27 | 28 | /// 29 | /// Converts the class data to ImGui. 30 | /// 31 | internal override void ToImGui() 32 | { 33 | base.ToImGui(); 34 | ImGui.Text($"Is Shrine Used: {this.IsUsed}"); 35 | } 36 | 37 | /// 38 | protected override void CleanUpData() 39 | { 40 | throw new Exception("Component Address should never be Zero."); 41 | } 42 | 43 | /// 44 | protected override void UpdateData(bool hasAddressChanged) 45 | { 46 | var reader = Core.Process.Handle; 47 | var data = reader.ReadMemory(this.Address); 48 | this.IsUsed = data.IsUsed; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/Components/TriggerableBlockage.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.Components 6 | { 7 | using System; 8 | using GameOffsets.Objects.Components; 9 | using ImGuiNET; 10 | 11 | /// 12 | /// The component in the entity. 13 | /// 14 | public class TriggerableBlockage : RemoteObjectBase 15 | { 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | /// address of the component. 20 | public TriggerableBlockage(IntPtr address) 21 | : base(address, true) { } 22 | 23 | /// 24 | /// Gets a value indicating whether TriggerableBlockage is closed or not. 25 | /// 26 | public bool IsBlocked { get; private set; } 27 | 28 | /// 29 | /// Converts the class data to ImGui. 30 | /// 31 | internal override void ToImGui() 32 | { 33 | base.ToImGui(); 34 | ImGui.Text($"Is Blocked: {this.IsBlocked}"); 35 | } 36 | 37 | /// 38 | protected override void CleanUpData() 39 | { 40 | throw new Exception("Component Address should never be Zero."); 41 | } 42 | 43 | /// 44 | protected override void UpdateData(bool hasAddressChanged) 45 | { 46 | var reader = Core.Process.Handle; 47 | var data = reader.ReadMemory(this.Address); 48 | this.IsBlocked = data.IsBlocked; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/GameWindowCull.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using Coroutine; 10 | using CoroutineEvents; 11 | using ImGuiNET; 12 | 13 | /// 14 | /// Reads the Game Window Cull (black bar on each side) values from the game. 15 | /// Only reads when game window moves/resize. 16 | /// 17 | public class GameWindowCull : RemoteObjectBase 18 | { 19 | /// 20 | /// Initializes a new instance of the class. 21 | /// 22 | /// address of the remote memory object. 23 | internal GameWindowCull(IntPtr address) 24 | : base(address) 25 | { 26 | CoroutineHandler.Start(this.OnGameMove(), priority: int.MaxValue); 27 | CoroutineHandler.Start(this.OnGameForegroundChange(), priority: int.MaxValue); 28 | } 29 | 30 | /// 31 | /// Gets the current game window scale values. 32 | /// 33 | public int Value { get; private set; } 34 | 35 | /// 36 | /// Converts the class data to ImGui. 37 | /// 38 | internal override void ToImGui() 39 | { 40 | base.ToImGui(); 41 | ImGui.Text($"Game Window Cull Size: {this.Value}"); 42 | } 43 | 44 | /// 45 | protected override void CleanUpData() 46 | { 47 | this.Value = 0; 48 | } 49 | 50 | /// 51 | protected override void UpdateData(bool hasAddressChanged) 52 | { 53 | var reader = Core.Process.Handle; 54 | this.Value = reader.ReadMemory(this.Address); 55 | } 56 | 57 | private IEnumerator OnGameMove() 58 | { 59 | while (true) 60 | { 61 | yield return new Wait(GameHelperEvents.OnMoved); 62 | 63 | // No need to check for IntPtr.zero 64 | // because game will only move when it exists. :D 65 | this.UpdateData(false); 66 | } 67 | } 68 | 69 | private IEnumerator OnGameForegroundChange() 70 | { 71 | while (true) 72 | { 73 | yield return new Wait(GameHelperEvents.OnForegroundChanged); 74 | 75 | // No need to check for IntPtr.zero 76 | // because game will only move when it exists. :D 77 | this.UpdateData(false); 78 | } 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/States/AreaLoadingState.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.States 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using Coroutine; 10 | using CoroutineEvents; 11 | using GameOffsets.Objects.States; 12 | using ImGuiNET; 13 | 14 | /// 15 | /// Reads AreaLoadingState Game Object. 16 | /// 17 | public sealed class AreaLoadingState : RemoteObjectBase 18 | { 19 | private AreaLoadingStateOffset lastCache; 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | /// address of the remote memory object. 25 | internal AreaLoadingState(IntPtr address) 26 | : base(address) 27 | { 28 | CoroutineHandler.Start(this.OnPerFrame(), priority: int.MaxValue - 1); 29 | } 30 | 31 | /// 32 | /// Gets the game current Area Name. 33 | /// 34 | public string CurrentAreaName { get; private set; } = string.Empty; 35 | 36 | /// 37 | /// Gets a value indicating whether the game is in loading screen or not. 38 | /// 39 | internal bool IsLoading { get; private set; } 40 | 41 | /// 42 | /// Converts the class data to ImGui. 43 | /// 44 | internal override void ToImGui() 45 | { 46 | base.ToImGui(); 47 | ImGui.Text($"Current Area Name: {this.CurrentAreaName}"); 48 | ImGui.Text($"Is Loading Screen: {this.IsLoading}"); 49 | ImGui.Text($"Total Loading Time(ms): {this.lastCache.TotalLoadingScreenTimeMs}"); 50 | } 51 | 52 | /// 53 | protected override void CleanUpData() 54 | { 55 | this.lastCache = default; 56 | this.CurrentAreaName = string.Empty; 57 | } 58 | 59 | /// 60 | protected override void UpdateData(bool hasAddressChanged) 61 | { 62 | var reader = Core.Process.Handle; 63 | var data = reader.ReadMemory(this.Address); 64 | this.IsLoading = data.IsLoading == 0x01; 65 | var hasAreaChanged = false; 66 | if (data.CurrentAreaName.Buffer != IntPtr.Zero && 67 | !this.IsLoading && 68 | data.TotalLoadingScreenTimeMs > this.lastCache.TotalLoadingScreenTimeMs) 69 | { 70 | var areaName = reader.ReadStdWString(data.CurrentAreaName); 71 | this.CurrentAreaName = areaName; 72 | this.lastCache = data; 73 | hasAreaChanged = true; 74 | } 75 | 76 | if (hasAreaChanged) 77 | { 78 | CoroutineHandler.InvokeLater(new Wait(0.1d), () => { CoroutineHandler.RaiseEvent(RemoteEvents.AreaChanged); }); 79 | } 80 | } 81 | 82 | private IEnumerator OnPerFrame() 83 | { 84 | while (true) 85 | { 86 | yield return new Wait(GameHelperEvents.PerFrameDataUpdate); 87 | if (this.Address != IntPtr.Zero) 88 | { 89 | this.UpdateData(false); 90 | } 91 | } 92 | } 93 | } 94 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/States/InGameState.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.States 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using Coroutine; 10 | using CoroutineEvents; 11 | using GameOffsets.Objects.States; 12 | using InGameStateObjects; 13 | using UiElement; 14 | 15 | /// 16 | /// Reads InGameState Game Object. 17 | /// 18 | public class InGameState : RemoteObjectBase 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | /// address of the remote memory object. 24 | internal InGameState(IntPtr address) 25 | : base(address) 26 | { 27 | Core.CoroutinesRegistrar.Add(CoroutineHandler.Start( 28 | this.OnPerFrame(), "[InGameState] Update Game State", int.MaxValue - 2)); 29 | } 30 | 31 | /// 32 | /// Gets the data related to the currently loaded world area. 33 | /// 34 | public WorldData CurrentWorldInstance { get; } 35 | 36 | = new(IntPtr.Zero); 37 | 38 | /// 39 | /// Gets the data related to the current area instance. 40 | /// 41 | public AreaInstance CurrentAreaInstance { get; } 42 | 43 | = new(IntPtr.Zero); 44 | 45 | /// 46 | /// Gets the UiRoot main child which contains all the UiElements of the game. 47 | /// 48 | public ImportantUiElements GameUi { get; } 49 | 50 | = new(IntPtr.Zero); 51 | 52 | /// 53 | /// Gets the data related to the root ui element. 54 | /// 55 | internal UiElementBase UiRoot { get; } 56 | 57 | = new(IntPtr.Zero); 58 | 59 | /// 60 | protected override void CleanUpData() 61 | { 62 | this.CurrentAreaInstance.Address = IntPtr.Zero; 63 | this.UiRoot.Address = IntPtr.Zero; 64 | this.GameUi.Address = IntPtr.Zero; 65 | this.CurrentWorldInstance.Address = IntPtr.Zero; 66 | } 67 | 68 | /// 69 | protected override void UpdateData(bool hasAddressChanged) 70 | { 71 | var reader = Core.Process.Handle; 72 | var data = reader.ReadMemory(this.Address); 73 | this.CurrentWorldInstance.Address = data.WorldData; 74 | this.CurrentAreaInstance.Address = data.AreaInstanceData; 75 | this.UiRoot.Address = data.UiRootPtr; 76 | this.GameUi.Address = data.IngameUi; 77 | } 78 | 79 | private IEnumerator OnPerFrame() 80 | { 81 | // TODO optimization: convert this into OnAreaChange. 82 | while (true) 83 | { 84 | yield return new Wait(GameHelperEvents.PerFrameDataUpdate); 85 | if (this.Address != IntPtr.Zero) 86 | { 87 | this.UpdateData(false); 88 | } 89 | } 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/States/InGameStateObjects/Item.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.States.InGameStateObjects 6 | { 7 | using System; 8 | using GameHelper.RemoteEnums; 9 | using GameOffsets.Objects.States.InGameState; 10 | 11 | /// 12 | /// Points to the item in the game. 13 | /// Item is basically anything that can be put in the inventory/stash. 14 | /// 15 | public class Item : Entity 16 | { 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// address of the Entity. 21 | internal Item(IntPtr address) 22 | : base(address) { } 23 | 24 | /// 25 | protected override void UpdateData(bool hasAddressChanged) 26 | { 27 | var reader = Core.Process.Handle; 28 | 29 | // NOTE: ItemStruct is defined in EntityOffsets.cs file. 30 | var itemData = reader.ReadMemory(this.Address); 31 | 32 | // this.Id will always be 0x00 because Items don't have 33 | // Id associated with them. 34 | this.IsValid = true; 35 | this.EntityType = EntityTypes.InventoryItem; 36 | this.UpdateComponentData(itemData, hasAddressChanged); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/TerrainHeightHelper.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects 6 | { 7 | using System; 8 | using ImGuiNET; 9 | 10 | /// 11 | /// Contains the static data for calculating the terrain height. 12 | /// 13 | public class TerrainHeightHelper : RemoteObjectBase 14 | { 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | /// address of the remote memory object. 19 | /// expected size of this remote memory object. 20 | internal TerrainHeightHelper(IntPtr address, int size) 21 | : base(address) 22 | { 23 | this.Values = new byte[size]; 24 | } 25 | 26 | /// 27 | /// Gets the values associated with this class. 28 | /// 29 | public byte[] Values { get; private set; } 30 | 31 | /// 32 | internal override void ToImGui() 33 | { 34 | base.ToImGui(); 35 | ImGui.Text(string.Join(' ', this.Values)); 36 | } 37 | 38 | /// 39 | protected override void CleanUpData() 40 | { 41 | for (var i = 0; i < this.Values.Length; i++) 42 | { 43 | this.Values[i] = 0; 44 | } 45 | } 46 | 47 | /// 48 | protected override void UpdateData(bool hasAddressChanged) 49 | { 50 | var reader = Core.Process.Handle; 51 | this.Values = reader.ReadMemoryArray(this.Address, this.Values.Length); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/UiElement/LargeMapUiElement.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.UiElement 6 | { 7 | using System; 8 | using System.Numerics; 9 | using ImGuiNET; 10 | 11 | /// 12 | /// Points to the LargeMap UiElement. 13 | /// It is exactly like any other element, except its in-memory position is its center 14 | /// 15 | public class LargeMapUiElement : MapUiElement 16 | { 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// address to the Map Ui Element of the game. 21 | internal LargeMapUiElement(IntPtr address) 22 | : base(address) { } 23 | 24 | /// 25 | public override Vector2 Postion => new(Core.GameCull.Value); 26 | 27 | /// 28 | public override Vector2 Size => new(Core.Process.WindowArea.Width - (Core.GameCull.Value * 2), Core.Process.WindowArea.Height); 29 | 30 | 31 | /// 32 | /// Gets the center of the map. 33 | /// 34 | public Vector2 Center => base.Postion; 35 | 36 | /// 37 | /// Converts the class data to ImGui. 38 | /// 39 | internal override void ToImGui() 40 | { 41 | base.ToImGui(); 42 | ImGui.Text($"Center (without shift/default-shift) {this.Center}"); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /GameHelper/RemoteObjects/UiElement/MapUiElement.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.RemoteObjects.UiElement 6 | { 7 | using System; 8 | using System.Numerics; 9 | using GameOffsets.Objects.UiElement; 10 | using ImGuiNET; 11 | 12 | /// 13 | /// Points to the Map UiElement. 14 | /// 15 | public class MapUiElement : UiElementBase 16 | { 17 | private Vector2 defaultShift = Vector2.Zero; 18 | private Vector2 shift = Vector2.Zero; 19 | 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | /// address to the Map Ui Element of the game. 24 | internal MapUiElement(IntPtr address) 25 | : base(address) { } 26 | 27 | /// 28 | /// Gets the value indicating how much map has shifted. 29 | /// 30 | public Vector2 Shift => this.shift; 31 | 32 | /// 33 | /// Gets the value indicating shifted amount at rest (default). 34 | /// 35 | public Vector2 DefaultShift => this.defaultShift; 36 | 37 | /// 38 | /// Gets the value indicating amount of zoom in the Map. 39 | /// Normally values are between 0.5f - 1.5f. 40 | /// 41 | public float Zoom { get; private set; } = 0.5f; 42 | 43 | /// 44 | /// Converts the class data to ImGui. 45 | /// 46 | internal override void ToImGui() 47 | { 48 | base.ToImGui(); 49 | ImGui.Text($"Shift {this.shift}"); 50 | ImGui.Text($"Default Shift {this.defaultShift}"); 51 | ImGui.Text($"Zoom {this.Zoom}"); 52 | } 53 | 54 | /// 55 | protected override void CleanUpData() 56 | { 57 | base.CleanUpData(); 58 | this.shift = default; 59 | this.defaultShift = default; 60 | this.Zoom = 0.5f; 61 | } 62 | 63 | /// 64 | protected override void UpdateData(bool hasAddressChanged) 65 | { 66 | base.UpdateData(hasAddressChanged); 67 | var reader = Core.Process.Handle; 68 | var data = reader.ReadMemory(this.Address); 69 | this.shift.X = data.Shift.X; 70 | this.shift.Y = data.Shift.Y; 71 | 72 | this.defaultShift.X = data.DefaultShift.X; 73 | this.defaultShift.Y = data.DefaultShift.Y; 74 | 75 | this.Zoom = data.Zoom; 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /GameHelper/Ui/DataVisualization.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.Ui 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using Coroutine; 11 | using CoroutineEvents; 12 | using ImGuiNET; 13 | using Utils; 14 | 15 | /// 16 | /// Visualize the and other miscellaneous data. 17 | /// 18 | public static class DataVisualization 19 | { 20 | /// 21 | /// Initializes the co-routines. 22 | /// 23 | internal static void InitializeCoroutines() 24 | { 25 | CoroutineHandler.Start(DataVisualizationRenderCoRoutine()); 26 | } 27 | 28 | /// 29 | /// Draws the window for Data Visualization. 30 | /// 31 | /// co-routine IWait. 32 | private static IEnumerator DataVisualizationRenderCoRoutine() 33 | { 34 | while (true) 35 | { 36 | yield return new Wait(GameHelperEvents.OnRender); 37 | if (!Core.GHSettings.ShowDataVisualization) 38 | { 39 | continue; 40 | } 41 | 42 | if (ImGui.Begin("Data Visualization", ref Core.GHSettings.ShowDataVisualization)) 43 | { 44 | if (ImGui.CollapsingHeader("Settings")) 45 | { 46 | var fields = Core.GHSettings.GetType().GetFields().ToList(); 47 | for (var i = 0; i < fields.Count; i++) 48 | { 49 | var field = fields[i]; 50 | ImGui.Text($"{field.Name}: {field.GetValue(Core.GHSettings)}"); 51 | } 52 | 53 | ImGui.Text($"Current SDL Window Size:{Core.Overlay.Size}"); 54 | ImGui.Text($"Current SDL Window Pos: {Core.Overlay.Position}"); 55 | } 56 | 57 | if (ImGui.CollapsingHeader("Game Process")) 58 | { 59 | if (Core.Process.Address != IntPtr.Zero) 60 | { 61 | ImGuiHelper.IntPtrToImGui("Base Address", Core.Process.Address); 62 | ImGui.Text($"Process: {Core.Process.Information}"); 63 | ImGui.Text($"WindowArea: {Core.Process.WindowArea}"); 64 | ImGui.Text($"Foreground: {Core.Process.Foreground}"); 65 | if (ImGui.TreeNode("Static Addresses")) 66 | { 67 | foreach (var saddr in Core.Process.StaticAddresses) 68 | { 69 | ImGuiHelper.IntPtrToImGui(saddr.Key, saddr.Value); 70 | } 71 | 72 | ImGui.TreePop(); 73 | } 74 | } 75 | else 76 | { 77 | ImGui.Text("Game not found."); 78 | } 79 | } 80 | 81 | Core.RemoteObjectsToImGuiCollapsingHeader(); 82 | } 83 | 84 | ImGui.End(); 85 | } 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /GameHelper/Ui/OverlayKiller.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.Ui 6 | { 7 | using System.Collections.Generic; 8 | using System.Diagnostics; 9 | using System.Numerics; 10 | using Coroutine; 11 | using CoroutineEvents; 12 | using ImGuiNET; 13 | 14 | /// 15 | /// Kills the overlay. 16 | /// 17 | public static class OverlayKiller 18 | { 19 | private static readonly Stopwatch Sw = Stopwatch.StartNew(); 20 | private static readonly int Timelimit = 20; 21 | private static readonly Vector2 Size = new(400); 22 | 23 | /// 24 | /// Initializes the co-routines. 25 | /// 26 | internal static void InitializeCoroutines() 27 | { 28 | CoroutineHandler.Start(OverlayKillerCoRoutine()); 29 | CoroutineHandler.Start(OnAreaChange()); 30 | } 31 | 32 | private static IEnumerator OverlayKillerCoRoutine() 33 | { 34 | while (true) 35 | { 36 | yield return new Wait(GameHelperEvents.OnRender); 37 | if (!Core.States.InGameStateObject.CurrentWorldInstance.AreaDetails.IsBattleRoyale) 38 | { 39 | Sw.Restart(); 40 | continue; 41 | } 42 | 43 | ImGui.SetNextWindowSize(Size); 44 | ImGui.Begin("Player Vs Player (PVP) Detected"); 45 | ImGui.TextWrapped("Please don't cheat in PvP mode. GameHelper was not " + 46 | "created for PvP cheating. Overlay will close " + 47 | $"in {Timelimit - (int)Sw.Elapsed.TotalSeconds} seconds."); 48 | ImGui.End(); 49 | 50 | if (Sw.Elapsed.TotalSeconds > Timelimit) 51 | { 52 | Core.Overlay.Close(); 53 | } 54 | } 55 | } 56 | 57 | private static IEnumerator OnAreaChange() 58 | { 59 | while (true) 60 | { 61 | yield return new Wait(RemoteEvents.AreaChanged); 62 | Sw.Restart(); 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /GameHelper/Utils/JsonHelper.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.Utils 6 | { 7 | using System.IO; 8 | using Newtonsoft.Json; 9 | 10 | /// 11 | /// Utility functions to help read/write to Json files. 12 | /// 13 | internal static class JsonHelper 14 | { 15 | /// 16 | /// Creates new instance or load from the file if file exists. 17 | /// 18 | /// Class name to (De)serialize. 19 | /// file to load from. 20 | /// class objecting containing the data (if data exits). 21 | public static T CreateOrLoadJsonFile(FileInfo file) 22 | where T : new() 23 | { 24 | file.Refresh(); 25 | file.Directory.Create(); 26 | if (file.Exists) 27 | { 28 | var content = File.ReadAllText(file.FullName); 29 | return JsonConvert.DeserializeObject(content); 30 | } 31 | 32 | T obj = new(); 33 | SafeToFile(obj, file); 34 | return obj; 35 | } 36 | 37 | /// 38 | /// Save the class object into the file. 39 | /// 40 | /// class object to save in the file. 41 | /// file to save in. 42 | public static void SafeToFile(object classObject, FileInfo file) 43 | { 44 | var content = JsonConvert.SerializeObject(classObject, Formatting.Indented); 45 | File.WriteAllText(file.FullName, content); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /GameHelper/Utils/MathHelper.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.Utils 6 | { 7 | using System.Numerics; 8 | 9 | /// 10 | /// Utility functions to help with some math. 11 | /// 12 | public static class MathHelper 13 | { 14 | /// 15 | /// Linearly interpolates between two points. 16 | /// Interpolates between the points a and b by the interpolant t. 17 | /// The parameter t is clamped to the range[0, 1]. 18 | /// This is most commonly used to find a point some fraction of the way along a line between two endpoints 19 | /// (e.g.to move an object gradually between those points). 20 | /// The value returned equals a + (b - a) * t (which can also be written a * (1-t) + b*t). 21 | /// When t = 0, Lerp(a, b, t) returns a. 22 | /// When t = 1, Lerp(a, b, t) returns b. 23 | /// When t = 0.5, Lerp(a, b, t) returns the point midway between a and b. 24 | /// 25 | /// Starting point. 26 | /// Destination point. 27 | /// Interpolation ratio. 28 | /// Interpolated value, equals to a + (b - a) * t. 29 | public static float Lerp(float a, float b, float t) 30 | { 31 | return a + (b - a) * t; 32 | } 33 | 34 | /// 35 | /// Linearly interpolates between two vectors. 36 | /// Interpolates between the vectors a and b by the interpolant t. 37 | /// The parameter t is clamped to the range[0, 1]. 38 | /// This is most commonly used to find a point some fraction of the way along a line between two endpoints 39 | /// (e.g.to move an object gradually between those points). 40 | /// Similar to . 41 | /// 42 | /// Starting point. 43 | /// Destination point. 44 | /// Interpolation ratio. 45 | /// Interpolated value, equals to a + (b - a) * t. 46 | public static Vector2 Lerp(Vector2 a, Vector2 b, float t) 47 | { 48 | return new Vector2(Lerp(a.X, b.X, t), Lerp(a.Y, b.Y, t)); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /GameHelper/Utils/RemoteObjectPropertyDetail.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameHelper.Utils 6 | { 7 | using System.Reflection; 8 | 9 | /// 10 | /// Stores some information about RemoteObject Property. 11 | /// 12 | internal struct RemoteObjectPropertyDetail 13 | { 14 | /// 15 | /// Name of the property. 16 | /// 17 | public string Name; 18 | 19 | /// 20 | /// Value of the property. 21 | /// 22 | public object Value; 23 | 24 | /// 25 | /// ToImGui method of the property. 26 | /// 27 | public MethodInfo ToImGui; 28 | } 29 | } -------------------------------------------------------------------------------- /GameOffsets/GameOffsets.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | false 6 | 7 | 8 | 9 | x64 10 | 1701;1702; 1591 11 | 12 | 13 | 14 | x64 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /GameOffsets/GameProcessName.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets 2 | { 3 | using System.Collections.Generic; 4 | 5 | public struct GameProcessDetails 6 | { 7 | /// 8 | /// Name of the Game Process (Normally name of the executable file without .exe) 9 | /// and the main window title. See task-manager to find the exact process name 10 | /// and convert the game to the window mode to see the window title on the game. 11 | /// 12 | public static readonly Dictionary ProcessName = new() 13 | { 14 | { "PathOfExile", "Path of Exile".ToLower() }, // also works on Garena 15 | { "PathOfExile_KG", "Path of Exile".ToLower() }, 16 | { "PathOfExileSteam", "Path of Exile".ToLower() }, 17 | { "PathOfExile_x64", "Path of Exile".ToLower() } 18 | }; 19 | 20 | public static readonly List Contributors = new() 21 | { 22 | "Dax***", 23 | "Scrippydoo", 24 | "Riyu", 25 | "Noneyatemp", 26 | "hienngocloveyou" 27 | }; 28 | } 29 | } -------------------------------------------------------------------------------- /GameOffsets/Natives/StdBucket.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Natives 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | /// 7 | /// Not sure the name of this structure. POE game uses it in a lot of different places 8 | /// it might be a stdbucket, std unordered_set or std_unordered_multiset. 9 | /// TODO: Create c++ HelloWorld program, 10 | /// Create these structures (name it var), 11 | /// Fill 1 value, 12 | /// Use cheat engine on that HelloWorld Program. 13 | /// HINT: use cout << &var << endl; to print memory address. 14 | /// NOTE: A reader function that uses this datastructure exists 15 | /// in SafeMemoryHandle class. If you modify this datastructure 16 | /// modify that function too. 17 | /// 18 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 19 | public struct StdBucket 20 | { 21 | public long PAD_00; 22 | public IntPtr Data; // ComponentArrayStructure 23 | public long Capacity; // actually, it's Capacity number - 1. 24 | public int Unknown3; // byte + padd 25 | public float Unknown4; 26 | public int PAD_20; // it's actually Counter (i.e. amount of items in the bucket) but unstable, do not use this. 27 | public int PAD_24; 28 | } 29 | 30 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 31 | public struct StdBucketNode 32 | where TValue : struct 33 | { 34 | public byte Flag0; 35 | public byte Flag1; 36 | public byte Flag2; 37 | public byte Flag3; 38 | public byte Flag4; 39 | public byte Flag5; 40 | public byte Flag6; 41 | public byte Flag7; 42 | 43 | public TValue Pointer0; 44 | public TValue Pointer1; 45 | public TValue Pointer2; 46 | public TValue Pointer3; 47 | public TValue Pointer4; 48 | public TValue Pointer5; 49 | public TValue Pointer6; 50 | public TValue Pointer7; 51 | 52 | public static byte InValidPointerFlagValue = 0xFF; 53 | } 54 | } -------------------------------------------------------------------------------- /GameOffsets/Natives/StdList.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Natives 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | /// 7 | /// A structure to read the c++ stdlist stored in the memory. 8 | /// NOTE: A reader function that uses this datastructure exists 9 | /// in SafeMemoryHandle class. If you modify this datastructure 10 | /// modify that function too. 11 | /// 12 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 13 | public struct StdList 14 | { 15 | public IntPtr Head; 16 | public int Size; // according to debugger this is long but for now int is working fine. 17 | public int PAD_C; 18 | } 19 | 20 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 21 | public struct StdListNode 22 | where TValue : struct 23 | { 24 | public IntPtr Next; 25 | public IntPtr Previous; 26 | public TValue Data; 27 | } 28 | 29 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 30 | public struct StdListNode 31 | { 32 | public IntPtr Next; 33 | public IntPtr Previous; 34 | } 35 | } -------------------------------------------------------------------------------- /GameOffsets/Natives/StdMap.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Natives 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | /// 7 | /// A structure to read the c++ stdmap stored in the memory. 8 | /// NOTE: A reader function that uses this datastructure exists 9 | /// in SafeMemoryHandle class. If you modify this datastructure 10 | /// modify that too. 11 | /// 12 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 13 | public struct StdMap 14 | { 15 | public IntPtr Head; 16 | public int Size; // according to debugger this is long but for now int is working fine. 17 | public int PAD_C; 18 | } 19 | 20 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 21 | public struct StdMapNode 22 | where TKey : struct 23 | where TValue : struct 24 | { 25 | public IntPtr Left; // 0x00 26 | public IntPtr Parent; // 0x08 27 | public IntPtr Right; // 0x10 28 | public byte Color; // 0x18 29 | public bool IsNil; // 0x19 30 | public byte pad_1A; 31 | public byte pad_1B; 32 | public uint pad_1C; 33 | public StdMapNodeData Data; // 0x20 34 | } 35 | 36 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 37 | public struct StdMapNodeData 38 | where TKey : struct 39 | where TValue : struct 40 | { 41 | public TKey Key; 42 | public TValue Value; 43 | } 44 | } -------------------------------------------------------------------------------- /GameOffsets/Natives/StdTuple2D.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Natives 2 | { 3 | using System.Runtime.InteropServices; 4 | 5 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 6 | public struct StdTuple2D 7 | { 8 | public T X; 9 | public T Y; 10 | 11 | public StdTuple2D(T x, T y) 12 | { 13 | this.X = x; 14 | this.Y = y; 15 | } 16 | 17 | public override string ToString() 18 | { 19 | return $"X: {this.X}, Y: {this.Y}"; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /GameOffsets/Natives/StdTuple3D.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Natives 2 | { 3 | using System.Runtime.InteropServices; 4 | 5 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 6 | public struct StdTuple3D 7 | { 8 | public T X; 9 | public T Y; 10 | public T Z; 11 | 12 | public override string ToString() 13 | { 14 | return $"X: {this.X}, Y: {this.Y}, Z: {this.Z}"; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /GameOffsets/Natives/StdVector.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Natives 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 7 | public struct StdVector 8 | { 9 | public IntPtr First; 10 | public IntPtr Last; 11 | public IntPtr End; 12 | 13 | /// 14 | /// Counts the number of elements in the StdVector. 15 | /// 16 | /// Number of bytes in 1 element. 17 | /// 18 | public long TotalElements(int elementSize) 19 | { 20 | return (this.Last.ToInt64() - this.First.ToInt64()) / elementSize; 21 | } 22 | 23 | public override string ToString() 24 | { 25 | return $"First: {this.First.ToInt64():X} - " + 26 | $"Last: {this.Last.ToInt64():X} - " + 27 | $"Size (bytes): {this.TotalElements(1)}"; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /GameOffsets/Natives/StdWString.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameOffsets.Natives 6 | { 7 | using System; 8 | using System.Runtime.InteropServices; 9 | 10 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 11 | public struct StdWString 12 | { 13 | public IntPtr Buffer; 14 | 15 | //// There is an optimization in std::wstring, where 16 | //// if a Capacity is less than or equal to 8 17 | //// then the wstring is stored locally (without a pointer). 18 | //// Since the pointer takes 8 bytes and 8 Capacity wstring takes 16 bytes 19 | //// wstring reserves 8 bytes over here which is then used to store the string. 20 | public IntPtr ReservedBytes; 21 | public int Length; // according to debugger this is long but for now int is working fine. 22 | public int PAD_14; 23 | public int Capacity; // according to debugger this is long but for now int is working fine. 24 | public int PAD_1C; 25 | 26 | public override string ToString() 27 | { 28 | return $"Buffer: {this.Buffer.ToInt64():X}, ReservedBytes: {this.ReservedBytes.ToInt64():X}, " + 29 | $"Length: {this.Length}, Capacity: {this.Capacity}"; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /GameOffsets/Natives/Util.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Natives 2 | { 3 | using System; 4 | 5 | public static class Util 6 | { 7 | /// 8 | /// Checks if the bit is set or not. Pos can be any number from 0 to 7. 9 | /// 10 | public static Func isBitSetByte = (x, pos) => (x & (1 << pos)) != 0; 11 | 12 | /// 13 | /// Checks if the bit is set or not. Pos can be any number from 0 to 31. 14 | /// 15 | public static Func isBitSetUint = (x, pos) => (x & (1 << pos)) != 0; 16 | } 17 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/AreaChangeOffset.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects 2 | { 3 | using System.Runtime.InteropServices; 4 | 5 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 6 | public struct AreaChangeOffset 7 | { 8 | public int counter; 9 | } 10 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/Components/Actor.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.Components 2 | { 3 | using System.Runtime.InteropServices; 4 | 5 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 6 | public struct ActorOffset 7 | { 8 | [FieldOffset(0x234)] public int AnimationId; 9 | } 10 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/Components/Base.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.Components 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 7 | public struct BaseOffsets 8 | { 9 | [FieldOffset(0x0000)] public ComponentHeader Header; 10 | [FieldOffset(0x0010)] public IntPtr BaseInternalPtr; //BaseItemTypes.dat 11 | } 12 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/Components/Buffs.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.Components 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | using Natives; 6 | 7 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 8 | public struct BuffsOffsets 9 | { 10 | [FieldOffset(0x000)] public ComponentHeader Header; 11 | [FieldOffset(0x158)] public StdVector StatusEffectPtr; 12 | } 13 | 14 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 15 | public struct StatusEffectStruct 16 | { 17 | [FieldOffset(0x0008)] public IntPtr BuffDefinationPtr; //// BuffDefination.DAT file 18 | [FieldOffset(0x0018)] public float TotalTime; 19 | 20 | [FieldOffset(0x001C)] public float TimeLeft; 21 | 22 | // [FieldOffset(0x0020)] public float unknown0; // always set to 1. 23 | [FieldOffset(0x0028)] public uint SourceEntityId; 24 | 25 | //[FieldOffset(0x0030)] public long Unknown1; 26 | //[FieldOffset(0x0038)] public int unknown2; 27 | [FieldOffset(0x003E)] public ushort Charges; // 2 bytes long but 1 is enough 28 | [FieldOffset(0x0042)] public byte Effectiveness; 29 | 30 | public override string ToString() 31 | { 32 | var maxTime = float.IsInfinity(this.TotalTime) ? "Inf" : this.TotalTime.ToString(); 33 | var timeLeft = float.IsInfinity(this.TimeLeft) ? "Inf" : this.TimeLeft.ToString(); 34 | return $"BuffDefinationPtr: {this.BuffDefinationPtr.ToInt64():X}, MaxTime: {maxTime}, " + 35 | $"TimeLeft: {timeLeft}, Charges: {this.Charges}, " + 36 | $"Effectiveness: {this.Effectiveness}, " + 37 | $"Source Entity Id: {this.SourceEntityId}"; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/Components/Charges.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.Components 2 | { 3 | using System.Runtime.InteropServices; 4 | 5 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 6 | public struct ChargesOffsets 7 | { 8 | [FieldOffset(0x0000)] public ComponentHeader Header; 9 | [FieldOffset(0x0018)] public int current; 10 | } 11 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/Components/Chest.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.Components 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 7 | public struct ChestOffsets 8 | { 9 | [FieldOffset(0x000)] public ComponentHeader Header; 10 | [FieldOffset(0x158)] public IntPtr ChestsDataPtr; 11 | [FieldOffset(0x160)] public bool IsOpened; 12 | } 13 | 14 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 15 | public struct ChestsStructInternal 16 | { 17 | [FieldOffset(0x21)] public bool IsLabelVisible; 18 | [FieldOffset(0x50)] public IntPtr StrongboxDatPtr; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /GameOffsets/Objects/Components/ComponentHeader.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.Components 2 | { 3 | using System.Runtime.InteropServices; 4 | 5 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 6 | public struct ComponentHeader 7 | { 8 | [FieldOffset(0x0000)] public long StaticPtr; 9 | [FieldOffset(0x0008)] public long EntityPtr; 10 | } 11 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/Components/Life.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.Components 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 7 | public struct LifeOffset 8 | { 9 | [FieldOffset(0x000)] public ComponentHeader Header; 10 | [FieldOffset(0x190)] public VitalStruct Mana; 11 | [FieldOffset(0x1C8)] public VitalStruct EnergyShield; 12 | [FieldOffset(0x228)] public VitalStruct Health; 13 | } 14 | 15 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 16 | public struct VitalStruct 17 | { 18 | public IntPtr PtrToLifeComponent; 19 | 20 | /// 21 | /// This is greater than zero if Vital is regenerating 22 | /// For value = 0 or less than 0, Vital isn't regenerating 23 | /// 24 | public float Regeneration; 25 | 26 | public int Total; 27 | 28 | public int Current; 29 | 30 | /// 31 | /// e.g. Clarity reserve flat Vital 32 | /// 33 | public int ReservedFlat; 34 | 35 | /// 36 | /// e.g. Heralds reserve % Vital. 37 | /// ReservedFlat does not change this value. 38 | /// Note that it's an integer, this is due to 20.23% is stored as 2023 39 | /// 40 | public int ReservedPercent; 41 | 42 | /// 43 | /// Final Reserved amount of Vital after all the calculations. 44 | /// 45 | public int ReservedTotal => (int)Math.Ceiling(this.ReservedPercent / 10000f * this.Total) + this.ReservedFlat; 46 | 47 | /// 48 | /// Final un-reserved amount of Vital after all the calculations. 49 | /// 50 | public int Unreserved => this.Total - this.ReservedTotal; 51 | 52 | /// 53 | /// Returns current Vital in percentage (excluding the reserved vital) or returns zero in case the Vital 54 | /// doesn't exists. 55 | /// 56 | /// 57 | public int CurrentInPercent() 58 | { 59 | if (this.Total == 0) 60 | { 61 | return 0; 62 | } 63 | 64 | return (int)Math.Round(100d * this.Current / this.Unreserved); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/Components/ObjectMagicProperties.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.Components 2 | { 3 | using System.Runtime.InteropServices; 4 | 5 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 6 | public struct ObjectMagicPropertiesOffsets 7 | { 8 | [FieldOffset(0x00)] public ComponentHeader Header; 9 | [FieldOffset(0x13C)] public int Rarity; 10 | } 11 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/Components/Player.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.Components 2 | { 3 | using System.Runtime.InteropServices; 4 | using Natives; 5 | 6 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 7 | public struct PlayerOffsets 8 | { 9 | [FieldOffset(0x000)] public ComponentHeader Header; 10 | [FieldOffset(0x160)] public StdWString Name; 11 | } 12 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/Components/Positioned.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.Components 2 | { 3 | using System.Runtime.InteropServices; 4 | 5 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 6 | public struct PositionedOffsets 7 | { 8 | [FieldOffset(0x000)] public ComponentHeader Header; 9 | 10 | [FieldOffset(0x1D9)] public byte Reaction; 11 | // [FieldOffset(0x1E8)] public StdTuple2D GridPosition; 12 | // [FieldOffset(0x214)] public StdTuple2D WorldPosition; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /GameOffsets/Objects/Components/Render.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.Components 2 | { 3 | using System.Runtime.InteropServices; 4 | using Natives; 5 | 6 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 7 | public struct RenderOffsets 8 | { 9 | [FieldOffset(0x0000)] public ComponentHeader Header; 10 | 11 | // Same as Positioned Component CurrentWorldPosition, 12 | // but this one contains Z axis; Z axis is where the HealthBar is. 13 | // If you want to use ground Z axis, swap current one with TerrainHeight. 14 | [FieldOffset(0x78)] public StdTuple3D CurrentWorldPosition; 15 | 16 | // Changing this value will move the in-game healthbar up/down. 17 | // Not sure if it's really X,Y,Z or something else. They all move 18 | // healthbar up/down. This might be useless. 19 | [FieldOffset(0x84)] public StdTuple3D CharactorModelBounds; 20 | // [FieldOffset(0x00A0)] public StdWString ClassName; 21 | 22 | // Exactly the same as provided in the Positioned component. 23 | // [FieldOffset(0x00C0)] public float RotationCurrent; 24 | // [FieldOffset(0x00C4)] public float RotationFuture; 25 | [FieldOffset(0xD8)] public float TerrainHeight; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /GameOffsets/Objects/Components/Shrine.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.Components 2 | { 3 | using System.Runtime.InteropServices; 4 | 5 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 6 | public struct ShrineOffsets 7 | { 8 | [FieldOffset(0x0000)] public ComponentHeader Header; 9 | 10 | // [FieldOffset(0x0020)] public int EntityIdWhoLastPickedTheShrine; 11 | [FieldOffset(0x0024)] public bool IsUsed; 12 | // [FieldOffset(0x0030)] public long ShrineDatRowPtr; //ShrineDatRowStruct 13 | } 14 | 15 | /* 16 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 17 | public struct ShrineDatRowStruct 18 | { 19 | [FieldOffset(0x0000)] public long IdString; 20 | //0 means it's not going to come back again. 21 | [FieldOffset(0x0008)] public int TimeoutInSeconds; 22 | [FieldOffset(0x000C)] public long DisplayName; 23 | [FieldOffset(0x0014)] public bool IsRegain; 24 | [FieldOffset(0x001D)] public bool PlayerShrineBuffDatRowPtr; //ShrineBuffDatStruct 25 | [FieldOffset(0x0025)] public int Unknown0; 26 | [FieldOffset(0x0029)] public int Unknown1; 27 | [FieldOffset(0x002D)] public long Description; 28 | [FieldOffset(0x0035)] public long MonsterShrineBuffDatRowPtr; //ShrineBuffDatStruct 29 | } 30 | 31 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 32 | public struct ShrineBuffDatStruct 33 | { 34 | [FieldOffset(0x0000)] public long IdString; 35 | [FieldOffset(0x0008)] public long BuffStatTotalKeys; 36 | [FieldOffset(0x0010)] public long BuffStatValuesPtr; //Ids (int) for BuffStats.dat 37 | [FieldOffset(0x0020)] public long BuffDefinationRowPtr; //BuffDefinations.DAT file Row 38 | } 39 | */ 40 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/Components/TriggerableBlockage.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.Components 2 | { 3 | using System.Runtime.InteropServices; 4 | 5 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 6 | public struct TriggerableBlockageOffsets 7 | { 8 | [FieldOffset(0x000)] public ComponentHeader Header; 9 | [FieldOffset(0x0030)] public bool IsBlocked; 10 | } 11 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/FilesStructures/BaseItemTypesDatOffsets.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.FilesStructures 2 | { 3 | using System.Runtime.InteropServices; 4 | using Natives; 5 | 6 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 7 | public struct BaseItemTypesDatOffsets 8 | { 9 | [FieldOffset(0x0030)] public StdWString BaseNamePtr; 10 | } 11 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/FilesStructures/WorldAreaDatOffsets.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.FilesStructures 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 7 | public struct WorldAreaDatOffsets 8 | { 9 | [FieldOffset(0x00)] public IntPtr IdPtr; 10 | [FieldOffset(0x08)] public IntPtr NamePtr; 11 | [FieldOffset(0x10)] public int Act; 12 | [FieldOffset(0x14)] public bool IsTown; 13 | [FieldOffset(0x15)] public bool HasWaypoint; 14 | } 15 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/GameStateOffsets.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | using Natives; 6 | 7 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 8 | public struct GameStateStaticOffset 9 | { 10 | [FieldOffset(0x00)] public IntPtr GameState; 11 | } 12 | 13 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 14 | public struct GameStateOffset 15 | { 16 | [FieldOffset(0x08)] public StdVector CurrentStatePtr; // Used in RemoteObject -> CurrentState 17 | [FieldOffset(0x48)] public IntPtr State0; 18 | [FieldOffset(0x58)] public IntPtr State1; 19 | [FieldOffset(0x68)] public IntPtr State2; 20 | [FieldOffset(0x78)] public IntPtr State3; 21 | [FieldOffset(0x88)] public IntPtr State4; 22 | [FieldOffset(0x98)] public IntPtr State5; 23 | [FieldOffset(0xA8)] public IntPtr State6; 24 | [FieldOffset(0xB8)] public IntPtr State7; 25 | [FieldOffset(0xC8)] public IntPtr State8; 26 | [FieldOffset(0xD8)] public IntPtr State9; 27 | [FieldOffset(0xE8)] public IntPtr State10; 28 | [FieldOffset(0xF8)] public IntPtr State11; 29 | } 30 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/LoadedFilesOffset.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | using Natives; 6 | 7 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 8 | public struct LoadedFilesRootObject 9 | { 10 | public StdBucket LoadedFiles; 11 | public static int TotalCount = 0x10; 12 | } 13 | 14 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 15 | public struct FilesPointerStructure 16 | { 17 | public IntPtr Useless0; 18 | public IntPtr FilesPointer; 19 | public IntPtr Useless1; 20 | } 21 | 22 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 23 | public struct FileInfoValueStruct 24 | { 25 | [FieldOffset(0x08)] public StdWString Name; 26 | 27 | //[FieldOffset(0x28)] public int FileType; 28 | //[FieldOffset(0x30)] public IntPtr UnknownPtr; 29 | [FieldOffset(0x38)] public int AreaChangeCount; 30 | 31 | // This saves a hell lot of memory but for debugging purposes 32 | // Feel free to set it to 0. 33 | public static readonly int IGNORE_FIRST_X_AREAS = 2; 34 | } 35 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/States/AreaLoadingStateOffset.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.States 2 | { 3 | using System.Runtime.InteropServices; 4 | using Natives; 5 | 6 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 7 | public struct AreaLoadingStateOffset 8 | { 9 | [FieldOffset(0xC8)] public int IsLoading; 10 | 11 | [FieldOffset(0x368)] public uint TotalLoadingScreenTimeMs; 12 | [FieldOffset(0x3A8)] public StdWString CurrentAreaName; // use isloading/totalLoadingScreenTimeMs offset diff 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /GameOffsets/Objects/States/InGameState/EntityOffsets.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.States.InGameState 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | using Natives; 6 | 7 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 8 | public struct ItemStruct 9 | { 10 | [FieldOffset(0x00)] public IntPtr VTablePtr; 11 | [FieldOffset(0x08)] public IntPtr EntityDetailsPtr; 12 | [FieldOffset(0x10)] public StdVector ComponentListPtr; 13 | } 14 | 15 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 16 | public struct EntityOffsets 17 | { 18 | [FieldOffset(0x00)] public ItemStruct ItemBase; 19 | [FieldOffset(0x30)] public StdVector UnknownListPtr; 20 | [FieldOffset(0x60)] public uint Id; 21 | [FieldOffset(0x70)] public byte IsValid; // 0x0C = Valid, 0x03 = Invalid 22 | } 23 | 24 | public static class EntityHelper 25 | { 26 | // 0th bit set = invalid. test byte ptr [rcx+5C],01 27 | // pass IsValid byte to this function. 28 | public static Func IsValidEntity = param => { return !Util.isBitSetByte(param, 0); }; 29 | 30 | public static Func IsFriendly = param => { return (param & 0x7F) == 0x01; }; 31 | } 32 | 33 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 34 | public struct EntityDetails 35 | { 36 | [FieldOffset(0x08)] public StdWString name; 37 | [FieldOffset(0x30)] public IntPtr ComponentLookUpPtr; 38 | } 39 | 40 | // DRY this with LoadedFilesOffset 41 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 42 | public struct ComponentLookUpStruct 43 | { 44 | [FieldOffset(0x00)] public IntPtr Unknown0; 45 | [FieldOffset(0x08)] public IntPtr Unknown1; 46 | [FieldOffset(0x10)] public StdVector Unknown2; 47 | [FieldOffset(0x28)] public StdBucket ComponentsNameAndIndex; 48 | } 49 | 50 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 51 | public struct ComponentNameAndIndexStruct 52 | { 53 | public IntPtr NamePtr; 54 | public int Index; 55 | public int PAD_0xC; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /GameOffsets/Objects/States/InGameState/ImportantUiElementsOffsets.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.States.InGameState 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | /// 7 | /// All offsets over here are UiElements. 8 | /// 9 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 10 | public struct ImportantUiElementsOffsets 11 | { 12 | [FieldOffset(0x678)] public IntPtr MapParentPtr; 13 | } 14 | 15 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 16 | public struct MapParentStruct 17 | { 18 | [FieldOffset(0x280)] public IntPtr LargeMapPtr; 19 | [FieldOffset(0x288)] public IntPtr MiniMapPtr; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /GameOffsets/Objects/States/InGameState/InventoryOffset.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.States.InGameState 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | using Natives; 6 | 7 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 8 | public struct PreInventoryStruct 9 | { 10 | [FieldOffset(0x10)] public IntPtr ptr; 11 | } 12 | 13 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 14 | public struct InventoryStruct 15 | { 16 | //[FieldOffset(0x00)] public int InventoryType; 17 | //[FieldOffset(0x04)] public int InventorySlot; 18 | //[FieldOffset(0x08)] public byte ShouldShowBoxes; // there are some other useless flags right after this byte. 19 | [FieldOffset(0x144)] public StdTuple2D TotalBoxes; // X * Y * 8 = StdVector.ItemList.Length. 20 | 21 | //[FieldOffset(0x18)] public int CanPutItem0; // setting this to 1 will block user from putting items. 22 | //[FieldOffset(0x1C)] public int CanPutItem1; // same as above. 23 | [FieldOffset(0x168)] public StdVector ItemList; 24 | 25 | // use ItemList, reading StdMap requires more reads than reading StdVector 26 | [FieldOffset(0x180)] public StdMap ItemsHashMap; 27 | 28 | // [FieldOffset(0x58)] public StdVector WierdUiElementsData; 29 | [FieldOffset(0x1C8)] public int ServerRequestCounter; 30 | } 31 | 32 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 33 | public struct ItemHashKey 34 | { 35 | public int ServerRequestCounterSnapShot; 36 | public int PAD_8; 37 | } 38 | 39 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 40 | public struct ItemHashValue 41 | { 42 | public IntPtr InventoryItemStructPtr; 43 | public IntPtr UselessItemPtr; 44 | } 45 | 46 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 47 | public struct InventoryItemStruct 48 | { 49 | [FieldOffset(0x00)] public IntPtr Item; // ItemStruct in EntityOffsets.cs 50 | [FieldOffset(0x08)] public StdTuple2D SlotStart; 51 | [FieldOffset(0x10)] public StdTuple2D SlotEnd; 52 | [FieldOffset(0x18)] public int ServerRequestCounterSnapShot; 53 | } 54 | } -------------------------------------------------------------------------------- /GameOffsets/Objects/States/InGameState/ServerDataOffset.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.States.InGameState 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | using Natives; 6 | 7 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 8 | public struct ServerDataStructure 9 | { 10 | public const int SKIP = 0x9300; // for reducing struct size. 11 | [FieldOffset(0x9288 + 0x278 - SKIP)] public StdVector PlayerInventories; // InventoryArrayStruct 12 | 13 | } 14 | 15 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 16 | public struct InventoryArrayStruct 17 | { 18 | [FieldOffset(0x00)] public int InventoryId; 19 | [FieldOffset(0x04)] public int PAD_0; 20 | [FieldOffset(0x08)] public IntPtr InventoryPtr0; // InventoryStruct 21 | [FieldOffset(0x10)] public IntPtr InventoryPtr1; // this points to 0x10 bytes before InventoryPtr0 22 | [FieldOffset(0x18)] public long PAD_1; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /GameOffsets/Objects/States/InGameState/WorldDataOffset.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace GameOffsets.Objects.States.InGameState 6 | { 7 | using System; 8 | using System.Numerics; 9 | using System.Runtime.InteropServices; 10 | 11 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 12 | public struct WorldDataOffset 13 | { 14 | [FieldOffset(0xA0)] public IntPtr WorldAreaDetailsPtr; 15 | [FieldOffset(0xA8)] public CameraStructure CameraStructurePtr; 16 | } 17 | 18 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 19 | public struct WorldAreaDetailsStruct 20 | { 21 | [FieldOffset(0x88)] public IntPtr WorldAreaDetailsRowPtr; // WorldArea.dat Offsets 22 | } 23 | 24 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 25 | public struct CameraStructure 26 | { 27 | [FieldOffset(0x00)] public IntPtr CodePtr; 28 | // [FieldOffset(0x8)] public int Width; 29 | // [FieldOffset(0xC)] public int Height; 30 | 31 | // First value is changing when we change the screen size (ratio) 32 | // 4 bytes before the matrix doesn't change 33 | // matrix is duplicated, meaning when first matrix finish, 2nd one start with exact same values. 34 | [FieldOffset(0x80)] public Matrix4x4 WorldToScreenMatrix; 35 | // [FieldOffset(0xF0)] public Vector3 Position; 36 | // [FieldOffset(0x1C4)] public float ZFar; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /GameOffsets/Objects/States/InGameStateOffset.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.States 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 7 | public struct InGameStateOffset 8 | { 9 | [FieldOffset(0x18)] public IntPtr AreaInstanceData; 10 | [FieldOffset(0x78)] public IntPtr WorldData; 11 | [FieldOffset(0x1A0)] public IntPtr UiRootPtr; 12 | [FieldOffset(0x450)] public IntPtr IngameUi; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /GameOffsets/Objects/UiElement/MapUiElement.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.UiElement 2 | { 3 | using System.Runtime.InteropServices; 4 | using Natives; 5 | 6 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 7 | public struct MapUiElementOffset 8 | { 9 | [FieldOffset(0x000)] public UiElementBaseOffset UiElementBase; 10 | [FieldOffset(0x270)] public StdTuple2D Shift; 11 | [FieldOffset(0x278)] public StdTuple2D DefaultShift; //new v2=(0, -20f) 12 | [FieldOffset(0x2B4)] public float Zoom; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /GameOffsets/Objects/UiElement/UiElementBaseOffset.cs: -------------------------------------------------------------------------------- 1 | namespace GameOffsets.Objects.UiElement 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | using Natives; 6 | 7 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 8 | public struct UiElementBaseOffset 9 | { 10 | [FieldOffset(0x000)] public IntPtr Vtable; 11 | [FieldOffset(0x028)] public IntPtr Self; 12 | 13 | [FieldOffset(0x030)] public StdVector ChildrensPtr; // both points to same children UiElements. 14 | 15 | // [FieldOffset(0x038)] public StdVector ChildrensPtr1; // both points to same children UiElements. 16 | [FieldOffset(0xA8)] public StdTuple2D PositionModifier; 17 | [FieldOffset(0xB0)] public StdWString Id; 18 | 19 | [FieldOffset(0xD2)] public byte ScaleIndex; 20 | 21 | // Following Ptr is basically pointing to InGameState+0x458. 22 | // No idea what InGameState+0x458 is pointing to. 23 | // [FieldOffset(0x088)] public IntPtr UnknownPtr; 24 | [FieldOffset(0xE0)] public IntPtr ParentPtr; // UiElement. 25 | [FieldOffset(0xE8)] public StdTuple2D RelativePosition; // variable 26 | 27 | [FieldOffset(0x100)] public float LocalScaleMultiplier; 28 | 29 | // [FieldOffset(0x108)] public float Scale; // !!do not use this!!, this scale provided by game is wrong. 30 | [FieldOffset(0x160)] public uint Flags; // variable 31 | 32 | [FieldOffset(0x180)] public StdTuple2D UnscaledSize; // variable 33 | // Tooltip???? 34 | } 35 | 36 | public static class UiElementBaseFuncs 37 | { 38 | private const int SHOULD_MODIFY_BINARY_POS = 0x0A; 39 | private const int IS_VISIBLE_BINARY_POS = 0x0B; 40 | 41 | public const int SCALE_INDEX_1 = 0x002; 42 | public const int SCALE_INDEX_3 = 0x004; 43 | public const int SCALE_INDEX_2 = 0x000; 44 | 45 | public static Func IsVisibleChecker = param => 46 | { 47 | return Util.isBitSetUint(param, IS_VISIBLE_BINARY_POS); 48 | }; 49 | 50 | public static Func ShouldModifyPos = param => 51 | { 52 | return Util.isBitSetUint(param, SHOULD_MODIFY_BINARY_POS); 53 | }; 54 | 55 | public static Func Unknown1 = param => { return Util.isBitSetUint(param, 0x02); }; 56 | 57 | public static Func Unknown2 = param => { return Util.isBitSetUint(param, 0x03); }; 58 | 59 | public static Func Unknown3 = param => { return Util.isBitSetUint(param, 0x13); }; 60 | } 61 | } -------------------------------------------------------------------------------- /HealthBars/Controller/SpriteController.cs: -------------------------------------------------------------------------------- 1 | namespace HealthBars.Controller 2 | { 3 | using System; 4 | using System.Globalization; 5 | using System.Numerics; 6 | using GameHelper; 7 | using GameHelper.Utils; 8 | using ImGuiNET; 9 | 10 | /// 11 | /// 12 | public class SpriteController 13 | { 14 | private readonly SpriteAtlas spriteAtlas; 15 | private readonly uint markColor = ImGuiHelper.Color(255, 255, 255, 100); 16 | 17 | /// 18 | /// Initialize SpriteController 19 | /// 20 | /// 21 | public SpriteController(SpriteAtlas spriteAtlas) 22 | { 23 | this.spriteAtlas = spriteAtlas; 24 | } 25 | 26 | /// 27 | /// Draw sprite from sprite atlas. 28 | /// 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | /// 37 | public void DrawSprite( 38 | string spriteName, 39 | Vector2 drawCoordinates, 40 | float scale, 41 | float virtualWidthFill, 42 | float virtualHeightFill, 43 | bool marks, 44 | bool border = false, 45 | uint borderColor = 0) 46 | { 47 | var sprite = this.spriteAtlas.GetSprite(spriteName); 48 | var offsetX = 0f; 49 | var offsetY = 23.17313f + Core.States.InGameStateObject.CurrentAreaInstance.Zoom * 14.69196f; 50 | 51 | if (sprite == null) 52 | { 53 | return; 54 | } 55 | 56 | var draw = ImGui.GetBackgroundDrawList(); 57 | 58 | var bounds = new Vector2( 59 | sprite.VirtualBounds.X * ((virtualWidthFill < 0 ? 100 : virtualWidthFill) / 100), 60 | sprite.VirtualBounds.Y * ((virtualHeightFill < 0 ? 100 : virtualHeightFill) / 100) 61 | ) * scale; 62 | var vBounds = sprite.VirtualBounds * scale; 63 | var half = new Vector2(offsetX + vBounds.X / 2, offsetY); 64 | var pos = drawCoordinates - half; 65 | 66 | draw.AddImage(this.spriteAtlas.TexturePtr, pos, pos + bounds, sprite.Uv[0], sprite.Uv[1]); 67 | 68 | if (marks) 69 | { 70 | Vector2 markLine = new(0, vBounds.Y - 1.5f); 71 | Vector2 mark25 = new(vBounds.X * 0.25f, 0); 72 | Vector2 mark50 = new(vBounds.X * 0.5f, 0); 73 | Vector2 mark75 = new(vBounds.X * 0.75f, 0); 74 | 75 | draw.AddLine(pos + mark25, pos + markLine + mark25, this.markColor); 76 | draw.AddLine(pos + mark50, pos + markLine + mark50, this.markColor); 77 | draw.AddLine(pos + mark75, pos + markLine + mark75, this.markColor); 78 | } 79 | 80 | if (border) 81 | { 82 | draw.AddRect(pos, pos + vBounds, borderColor, 0f, ImDrawFlags.RoundCornersNone, 4f); 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /HealthBars/HealthBars.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Library 5 | net5.0 6 | true 7 | 8 | 9 | 10 | x64 11 | 12 | 13 | 14 | x64 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | false 25 | false 26 | 27 | 28 | 29 | 30 | 31 | PreserveNewest 32 | 33 | 34 | PreserveNewest 35 | 36 | 37 | 38 | 39 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /HealthBars/Sprite.cs: -------------------------------------------------------------------------------- 1 | namespace HealthBars 2 | { 3 | using System.Numerics; 4 | 5 | /// 6 | /// Sprite class. 7 | /// 8 | public class Sprite 9 | { 10 | /// 11 | /// Sprite virtual outer space. 12 | /// 13 | public readonly Vector2 VirtualBounds; 14 | 15 | /// 16 | /// Initialization of instance. 17 | /// 18 | /// 19 | /// 20 | /// 21 | public Sprite(CubeObject frame, CubeObject spriteSheetSize, Vector2 virtualBounds) 22 | { 23 | this.VirtualBounds = virtualBounds; 24 | 25 | this.X = frame.X; 26 | this.Y = frame.Y; 27 | this.W = frame.W; 28 | this.H = frame.H; 29 | 30 | this.Uv = new Vector2[] 31 | { 32 | new(this.X / spriteSheetSize.W, this.Y / spriteSheetSize.H), 33 | new((this.X + this.W) / spriteSheetSize.W, (this.Y + this.H) / spriteSheetSize.H) 34 | }; 35 | } 36 | 37 | /// 38 | /// Precalculated uv. 39 | /// 40 | public Vector2[] Uv { get; } 41 | 42 | private float H { get; } 43 | private float W { get; } 44 | private float X { get; } 45 | private float Y { get; } 46 | } 47 | } -------------------------------------------------------------------------------- /HealthBars/SpritesheetMetadata.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable All 2 | 3 | #pragma warning disable 1591 4 | namespace HealthBars 5 | { 6 | using System.Collections.Concurrent; 7 | using System.Text.Json.Serialization; 8 | 9 | public class SpritesheetMetadata 10 | { 11 | [JsonPropertyName("frames")] public ConcurrentDictionary Frames; 12 | 13 | [JsonPropertyName("meta")] public MetaObject Meta; 14 | } 15 | 16 | public class FrameObject 17 | { 18 | [JsonPropertyName("frame")] public CubeObject Frame; 19 | 20 | [JsonPropertyName("rotated")] public bool Rotated; 21 | 22 | [JsonPropertyName("sourceSize")] public CubeObject SourceSize; 23 | 24 | [JsonPropertyName("spriteSourceSize")] public CubeObject SpriteSourceSize; 25 | 26 | [JsonPropertyName("trimmed")] public bool Trimmed; 27 | } 28 | 29 | public class MetaObject 30 | { 31 | [JsonPropertyName("app")] public string App; 32 | 33 | [JsonPropertyName("format")] public string Format; 34 | 35 | [JsonPropertyName("image")] public string Image; 36 | 37 | [JsonPropertyName("scale")] public float Scale; 38 | 39 | [JsonPropertyName("size")] public CubeObject Size; 40 | 41 | [JsonPropertyName("version")] public string Version; 42 | } 43 | 44 | public class CubeObject 45 | { 46 | [JsonPropertyName("h")] public float H; 47 | 48 | [JsonPropertyName("w")] public float W; 49 | 50 | [JsonPropertyName("x")] public float X; 51 | 52 | [JsonPropertyName("y")] public float Y; 53 | } 54 | } -------------------------------------------------------------------------------- /HealthBars/View/Entities/CommonFriendly.cs: -------------------------------------------------------------------------------- 1 | namespace HealthBars.View.Entities 2 | { 3 | using System.Numerics; 4 | using Controller; 5 | 6 | /// 7 | public abstract class CommonFriendly : Default 8 | { 9 | /// 10 | /// Adds an Energy shield bar 11 | /// 12 | /// 13 | /// 14 | /// 15 | protected static void AddEnergyShieldBar(SpriteController spriteController, EntityParams eP, float scale) 16 | { 17 | var healthPos = eP.Pos + new Vector2(0, 1) * scale; 18 | spriteController.DrawSprite("ES", healthPos, scale, eP.EsPercent, -1, false, eP.DrawBorder, eP.BorderColor); 19 | } 20 | 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | protected static void AddHealthBar(SpriteController spriteController, EntityParams eP, float scale) 27 | { 28 | var hpPos = eP.Pos + new Vector2(0, 1) * scale; 29 | spriteController.DrawSprite("EmptyHP", hpPos, scale, 100f - eP.HpReserved, -1, false); 30 | spriteController.DrawSprite("HP", hpPos, scale, eP.HpPercent, -1, eP.Settings.ShowFriendlyGradationMarks); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /HealthBars/View/Entities/CurrentPlayer.cs: -------------------------------------------------------------------------------- 1 | namespace HealthBars.View.Entities 2 | { 3 | using Controller; 4 | 5 | /// 6 | public class CurrentPlayer : CommonFriendly 7 | { 8 | /// 9 | public override void Draw(EntityParams eP, SpriteController spriteController) 10 | { 11 | var scale = RarityBarScale(eP); 12 | 13 | AddDoubleEmptyBar(spriteController, eP, scale); 14 | AddManaBar(spriteController, eP, scale); 15 | AddHealthBar(spriteController, eP, scale); 16 | if (eP.EsTotal > 0) 17 | { 18 | AddEnergyShieldBar(spriteController, eP, scale); 19 | } 20 | } 21 | 22 | /// 23 | public override bool ShouldDraw(EntityParams entityParams) 24 | { 25 | return entityParams.Settings.ShowPlayerBars; 26 | } 27 | 28 | private static float RarityBarScale(EntityParams entityParams) 29 | { 30 | return entityParams.Settings.PlayerBarScale; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /HealthBars/View/Entities/Default.cs: -------------------------------------------------------------------------------- 1 | namespace HealthBars.View.Entities 2 | { 3 | using System.Numerics; 4 | using Controller; 5 | 6 | /// 7 | public abstract class Default : IEntity 8 | { 9 | /// 10 | public abstract void Draw(EntityParams eP, SpriteController spriteController); 11 | 12 | /// 13 | public abstract bool ShouldDraw(EntityParams entityParams); 14 | 15 | /// 16 | /// Draws an empty bar sprite 17 | /// 18 | /// 19 | /// 20 | /// 21 | protected static void AddEmptyBar(SpriteController spriteController, EntityParams eP, float scale) 22 | { 23 | spriteController.DrawSprite("MonsterBar", eP.Pos, scale, -1, -1, false, eP.DrawBorder, eP.BorderColor); 24 | } 25 | 26 | /// 27 | /// Draws a double empty bar sprite 28 | /// 29 | /// 30 | /// 31 | /// 32 | protected static void AddDoubleEmptyBar(SpriteController spriteController, EntityParams eP, float scale) 33 | { 34 | spriteController.DrawSprite("PlayerBars", eP.Pos, scale, -1, -1, false, eP.DrawBorder, eP.BorderColor); 35 | } 36 | 37 | 38 | /// 39 | /// Draws a mana bar sprite 40 | /// 41 | /// 42 | /// 43 | /// 44 | protected static void AddManaBar(SpriteController spriteController, EntityParams eP, float scale) 45 | { 46 | var manaPos = eP.Pos + new Vector2(0, 10) * scale; 47 | 48 | spriteController.DrawSprite("EmptyMana", manaPos, scale, 100f - eP.ManaReserved, -1, false); 49 | spriteController.DrawSprite("Mana", manaPos, scale, eP.ManaPercent, -1, false); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /HealthBars/View/Entities/Enemy.cs: -------------------------------------------------------------------------------- 1 | namespace HealthBars.View.Entities 2 | { 3 | using System.Numerics; 4 | using Controller; 5 | using GameHelper.RemoteEnums; 6 | using GameHelper.Utils; 7 | 8 | /// 9 | public class Enemy : Default 10 | { 11 | /// 12 | public override void Draw(EntityParams eP, SpriteController spriteController) 13 | { 14 | var scale = RarityBarScale(eP); 15 | 16 | if (eP.Settings.ShowEnemyMana) 17 | { 18 | AddDoubleEmptyBar(spriteController, eP, scale); 19 | AddManaBar(spriteController, eP, scale); 20 | } 21 | else 22 | { 23 | AddEmptyBar(spriteController, eP, scale); 24 | } 25 | 26 | AddHealthBar(spriteController, eP, scale); 27 | } 28 | 29 | /// 30 | public override bool ShouldDraw(EntityParams entityParams) 31 | { 32 | var rarity = entityParams.Rarity; 33 | var settings = entityParams.Settings; 34 | 35 | return entityParams.HasMagicProperties && ( 36 | rarity == Rarity.Normal && settings.ShowNormalBar || 37 | rarity == Rarity.Magic && settings.ShowMagicBar || 38 | rarity == Rarity.Rare && settings.ShowRareBar || 39 | rarity == Rarity.Unique && settings.ShowUniqueBar 40 | ); 41 | } 42 | 43 | private static void AddHealthBar(SpriteController spriteController, EntityParams eP, float scale) 44 | { 45 | var hpPos = eP.Pos + new Vector2(0, 1) * scale; 46 | spriteController.DrawSprite("EmptyHP", hpPos, scale, 100f - eP.HpReserved, -1, false); 47 | 48 | var inCullingRange = InCullingRange(eP, eP.HpPercent); 49 | var cullingColor = ImGuiHelper.Color(eP.Settings.CullRangeColor * 255f); 50 | spriteController.DrawSprite("EnemyHP", hpPos, scale, eP.HpPercent, -1, eP.Settings.ShowEnemyGradationMarks, 51 | inCullingRange, cullingColor); 52 | } 53 | 54 | private static float RarityBarScale(EntityParams entityParams) 55 | { 56 | return entityParams.Rarity switch 57 | { 58 | Rarity.Unique => entityParams.Settings.UniqueBarScale, 59 | Rarity.Rare => entityParams.Settings.RareBarScale, 60 | Rarity.Magic => entityParams.Settings.MagicBarScale, 61 | _ => entityParams.Settings.NormalBarScale 62 | }; 63 | } 64 | 65 | private static bool InCullingRange(EntityParams entityParams, float hpPercent) 66 | { 67 | return entityParams.ShowCulling && hpPercent > 0 && hpPercent < entityParams.Settings.CullingRange; 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /HealthBars/View/Entities/Friendly.cs: -------------------------------------------------------------------------------- 1 | namespace HealthBars.View.Entities 2 | { 3 | using Controller; 4 | 5 | /// 6 | public class Friendly : CommonFriendly 7 | { 8 | /// 9 | public override void Draw(EntityParams eP, SpriteController spriteController) 10 | { 11 | var scale = RarityBarScale(eP); 12 | 13 | AddEmptyBar(spriteController, eP, scale); 14 | AddHealthBar(spriteController, eP, scale); 15 | if (eP.EsTotal > 0) 16 | { 17 | AddEnergyShieldBar(spriteController, eP, scale); 18 | } 19 | } 20 | 21 | /// 22 | public override bool ShouldDraw(EntityParams entityParams) 23 | { 24 | return entityParams.Settings.ShowFriendlyBars; 25 | } 26 | 27 | 28 | private static float RarityBarScale(EntityParams entityParams) 29 | { 30 | return entityParams.Settings.FriendlyBarScale; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /HealthBars/View/Entities/IEntity.cs: -------------------------------------------------------------------------------- 1 | namespace HealthBars.View.Entities 2 | { 3 | using Controller; 4 | 5 | /// 6 | /// 7 | public interface IEntity 8 | { 9 | /// 10 | /// 11 | /// 12 | /// 13 | public void Draw(EntityParams eP, SpriteController spriteController); 14 | 15 | /// 16 | /// 17 | /// 18 | /// 19 | public bool ShouldDraw(EntityParams entityParams); 20 | } 21 | } -------------------------------------------------------------------------------- /HealthBars/View/Entities/Invalid.cs: -------------------------------------------------------------------------------- 1 | namespace HealthBars.View.Entities 2 | { 3 | using System; 4 | using System.Numerics; 5 | using Controller; 6 | using GameHelper.RemoteEnums; 7 | using GameHelper.Utils; 8 | 9 | /// 10 | public class Invalid : Default 11 | { 12 | /// 13 | public override void Draw(EntityParams eP, SpriteController spriteController) 14 | { 15 | throw new Exception("Can not draw invalid entity."); 16 | } 17 | 18 | /// 19 | public override bool ShouldDraw(EntityParams entityParams) 20 | { 21 | throw new Exception("Can not draw invalid entity."); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /HealthBars/View/EntityFactory.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | namespace HealthBars.View 3 | { 4 | using Entities; 5 | using GameHelper; 6 | using GameHelper.RemoteObjects.Components; 7 | using GameHelper.RemoteObjects.States.InGameStateObjects; 8 | 9 | /// 10 | /// 11 | public class EntityFactory 12 | { 13 | private readonly Invalid invalid = new(); 14 | private readonly Enemy enemy = new(); 15 | private readonly Friendly friendly = new(); 16 | private readonly CurrentPlayer player = new(); 17 | 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | public bool TryGetEntity(Entity entity, out IEntity drawEntity) 24 | { 25 | drawEntity = this.invalid; 26 | var hasVital = entity.TryGetComponent(out var entityLife); 27 | if (!hasVital || !entityLife.IsAlive) 28 | { 29 | return false; 30 | } 31 | 32 | var isBlockage = entity.TryGetComponent(out _); 33 | if (isBlockage) 34 | { 35 | return false; 36 | } 37 | 38 | var hasRender = entity.TryGetComponent(out _); 39 | if (!hasRender) 40 | { 41 | return false; 42 | } 43 | 44 | var hasPositioned = entity.TryGetComponent(out var positioned); 45 | if (!hasPositioned) 46 | { 47 | return false; 48 | } 49 | 50 | var isPlayer = entity.TryGetComponent(out _); 51 | var hasMagicProperties = entity.TryGetComponent(out _); 52 | if (!hasMagicProperties && !isPlayer) 53 | { 54 | return false; 55 | } 56 | 57 | var willDieAfterTime = entity.TryGetComponent(out _); 58 | if (willDieAfterTime) 59 | { 60 | return false; 61 | } 62 | 63 | var isCurrentPlayer = 64 | entity.Address == Core.States.InGameStateObject.CurrentAreaInstance.Player.Address; 65 | 66 | if (isCurrentPlayer) 67 | { 68 | drawEntity = this.player; 69 | return true; 70 | } 71 | 72 | var isFriendly = positioned.IsFriendly; 73 | if (isFriendly) 74 | { 75 | drawEntity = this.friendly; 76 | return true; 77 | } 78 | 79 | drawEntity = this.enemy; 80 | return true; 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /HealthBars/sprites/ES.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BanditTech/GameOverlay/bc73cedc0b7e362b3007c93decede42b9ca6d635/HealthBars/sprites/ES.png -------------------------------------------------------------------------------- /HealthBars/sprites/EmptyHP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BanditTech/GameOverlay/bc73cedc0b7e362b3007c93decede42b9ca6d635/HealthBars/sprites/EmptyHP.png -------------------------------------------------------------------------------- /HealthBars/sprites/EmptyMana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BanditTech/GameOverlay/bc73cedc0b7e362b3007c93decede42b9ca6d635/HealthBars/sprites/EmptyMana.png -------------------------------------------------------------------------------- /HealthBars/sprites/EnemyHP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BanditTech/GameOverlay/bc73cedc0b7e362b3007c93decede42b9ca6d635/HealthBars/sprites/EnemyHP.png -------------------------------------------------------------------------------- /HealthBars/sprites/HP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BanditTech/GameOverlay/bc73cedc0b7e362b3007c93decede42b9ca6d635/HealthBars/sprites/HP.png -------------------------------------------------------------------------------- /HealthBars/sprites/Mana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BanditTech/GameOverlay/bc73cedc0b7e362b3007c93decede42b9ca6d635/HealthBars/sprites/Mana.png -------------------------------------------------------------------------------- /HealthBars/sprites/MonsterBar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BanditTech/GameOverlay/bc73cedc0b7e362b3007c93decede42b9ca6d635/HealthBars/sprites/MonsterBar.png -------------------------------------------------------------------------------- /HealthBars/sprites/PlayerBars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BanditTech/GameOverlay/bc73cedc0b7e362b3007c93decede42b9ca6d635/HealthBars/sprites/PlayerBars.png -------------------------------------------------------------------------------- /HealthBars/spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BanditTech/GameOverlay/bc73cedc0b7e362b3007c93decede42b9ca6d635/HealthBars/spritesheet.png -------------------------------------------------------------------------------- /Launcher/AutoUpdate.cs: -------------------------------------------------------------------------------- 1 | namespace Launcher 2 | { 3 | using Newtonsoft.Json; 4 | using Newtonsoft.Json.Linq; 5 | using System; 6 | using System.Diagnostics; 7 | using System.IO; 8 | using System.Net; 9 | 10 | public static class AutoUpdate 11 | { 12 | private static string upgrade_url = "https://api.github.com/repos/BanditTech/GameOverlay/releases/latest"; 13 | private static string version_file_name = "VERSION.txt"; 14 | private static string release_file_name = "release.zip"; 15 | private static string self_exe_name = AppDomain.CurrentDomain.FriendlyName; 16 | 17 | private static JObject get_latest_version_info() 18 | { 19 | var httpWebRequest = (HttpWebRequest)WebRequest.Create(upgrade_url); 20 | httpWebRequest.ContentType = "application/json"; 21 | httpWebRequest.Accept = "*/*"; 22 | httpWebRequest.Method = "GET"; 23 | httpWebRequest.UserAgent = "curl/7.83.0"; 24 | var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse(); 25 | using var streamReader = new StreamReader(httpResponse.GetResponseStream()); 26 | var jsonObject = JsonConvert.DeserializeObject(streamReader.ReadToEnd()); 27 | return jsonObject; 28 | } 29 | 30 | private static string extract_download_url(JObject info) 31 | { 32 | var asserts = info["assets"]; 33 | foreach (var assert in asserts) 34 | { 35 | if (assert["name"].ToString() == release_file_name) 36 | { 37 | return assert["browser_download_url"].ToString(); 38 | } 39 | } 40 | 41 | return string.Empty; 42 | } 43 | 44 | public static bool UpgradeGameHelper(string gameHelperDir) 45 | { 46 | var versionFile = Path.Combine(gameHelperDir, version_file_name); 47 | if (!File.Exists(versionFile)) 48 | { 49 | Console.WriteLine($"{versionFile} is missing, skipping upgrade process."); 50 | return false; 51 | } 52 | 53 | var currentVersion = File.ReadAllText(versionFile).Trim(); 54 | var info = get_latest_version_info(); 55 | string latestVersion; 56 | if (info["tag_name"] != null) 57 | { 58 | latestVersion = info["tag_name"].ToString(); 59 | } 60 | else 61 | { 62 | Console.WriteLine($"Failed to upgrade because I couldn't find tag in {info}."); 63 | return false; 64 | } 65 | 66 | var downloadUrl = extract_download_url(info); 67 | if (string.IsNullOrEmpty(downloadUrl)) 68 | { 69 | Console.WriteLine($"Upgrade failed because I couldn't find {release_file_name} in {info}."); 70 | return false; 71 | } 72 | 73 | if (currentVersion != latestVersion) 74 | { 75 | Console.WriteLine($"Your version is {currentVersion}. Latest version is {latestVersion}, downloading now..."); 76 | using var client = new WebClient(); 77 | client.DownloadFile(downloadUrl, release_file_name); 78 | Process.Start("powershell.exe", $"Start-sleep -Seconds 3; Expand-Archive -Force {release_file_name} .; Remove-Item -Force {release_file_name}; ./{self_exe_name}.exe -Force"); 79 | return true; 80 | 81 | } 82 | 83 | return false; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Launcher/GameHelperFinder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace Launcher 6 | { 7 | using System; 8 | using System.IO; 9 | using System.Reflection; 10 | 11 | public static class GameHelperFinder 12 | { 13 | private const string GameHelperFileName = "GameHelper.exe"; 14 | 15 | /// 16 | /// Finds the GameHelper on the file system. 17 | /// 18 | /// directory in which game helper is located 19 | /// path to game helper exe file 20 | /// 21 | public static bool TryFindGameHelperExe(out string gameHelperDir, out string gameHelperLoc) 22 | { 23 | gameHelperDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 24 | gameHelperLoc = Path.Join(gameHelperDir, GameHelperFileName); 25 | if (!new FileInfo(gameHelperLoc).Exists) 26 | { 27 | Console.WriteLine($"GameHelper.exe not found in {gameHelperDir} directory."); 28 | Console.Write("Provide GameHelper.exe path:"); 29 | var path = Console.ReadLine().Trim(); 30 | if (File.GetAttributes(path).HasFlag(FileAttributes.Directory)) 31 | { 32 | gameHelperDir = path; 33 | } 34 | else 35 | { 36 | gameHelperDir = Path.GetDirectoryName(path); 37 | } 38 | 39 | gameHelperLoc = Path.Join(gameHelperDir, GameHelperFileName); 40 | if (!new FileInfo(gameHelperLoc).Exists) 41 | { 42 | return false; 43 | } 44 | } 45 | 46 | return true; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Launcher/GameHelperTransformer.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace Launcher 6 | { 7 | using System.IO; 8 | using AsmResolver.PE; 9 | using AsmResolver.PE.File; 10 | using AsmResolver.PE.File.Headers; 11 | using AsmResolver.PE.Win32Resources.Builder; 12 | using AsmResolver.PE.Win32Resources.Version; 13 | 14 | /// 15 | /// A helper class to transform the GameHelper tool name and metadata info. 16 | /// 17 | public static class GameHelperTransformer 18 | { 19 | /// 20 | /// Transforms the GameHelper tool name and metadata info. 21 | /// 22 | /// string to replace the name and metadata info with. 23 | /// 24 | public static string TransformGameHelperExecutable(string gameHelperDir, string gameHelperLoc, string newName) 25 | { 26 | var newPath = Path.Join(gameHelperDir, $"{newName}.exe"); 27 | TemporaryFileManager.AddFile(newPath); 28 | TransformExecutable(gameHelperLoc, newPath, newName); 29 | return newPath; 30 | } 31 | 32 | private static void TransformExecutable(string inputPath, string outputPath, string infoName) 33 | { 34 | var peFile = PEFile.FromFile(inputPath); 35 | var peImage = PEImage.FromFile(peFile); 36 | var versionInfo = VersionInfoResource.FromDirectory(peImage.Resources); 37 | var stringInfo = versionInfo.GetChild(StringFileInfo.StringFileInfoKey); 38 | var stringTable = stringInfo.Tables[0]; 39 | stringTable[StringTable.CommentsKey] = ""; 40 | stringTable[StringTable.CompanyNameKey] = infoName; 41 | stringTable[StringTable.FileDescriptionKey] = infoName; 42 | stringTable[StringTable.InternalNameKey] = infoName; 43 | stringTable[StringTable.OriginalFilenameKey] = Path.GetFileName(outputPath); 44 | stringTable[StringTable.ProductNameKey] = infoName; 45 | versionInfo.WriteToDirectory(peImage.Resources); 46 | var resourceDirectoryBuffer = new ResourceDirectoryBuffer(); 47 | resourceDirectoryBuffer.AddDirectory(peImage.Resources); 48 | var directory = peFile.OptionalHeader.GetDataDirectory(DataDirectoryIndex.ResourceDirectory); 49 | var section = peFile.GetSectionContainingRva(directory.VirtualAddress); 50 | section.Contents = resourceDirectoryBuffer; 51 | peFile.Write(outputPath); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Launcher/Launcher.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net5.0 6 | app.manifest 7 | Launcher.Program 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Launcher/LocationValidator.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace Launcher 6 | { 7 | using System; 8 | using System.IO; 9 | using System.Reflection; 10 | using System.Text.RegularExpressions; 11 | 12 | /// 13 | /// A helper class to validate location. 14 | /// 15 | public static class LocationValidator 16 | { 17 | private static readonly Regex BadNameRegex = new( 18 | @"poe|path\s*of\s*exile|overlay|helper|hud|desktop", 19 | RegexOptions.IgnoreCase); 20 | 21 | /// 22 | /// Checks the GameHelper tool path name to make sure it doesn't have any bad information. 23 | /// If it does, print the issue to the stdout. 24 | /// 25 | /// returns true in case of good path otherwise false. 26 | public static bool IsGameHelperLocationGood(out string message) 27 | { 28 | message = null; 29 | var currentProcessPath = Assembly.GetExecutingAssembly().Location; 30 | var directoryPath = Path.GetDirectoryName(currentProcessPath); 31 | var pathMatch = BadNameRegex.Match(directoryPath); 32 | if (pathMatch.Success) 33 | { 34 | message = $"You have downloaded GameHelper in a bad folder/pathname. " + 35 | $"Your folder/pathname contains \"{pathMatch.Value}\". " + 36 | $"This is bad for your account. Please rename/move GameHelper to a better folder/pathname."; 37 | return false; 38 | } 39 | 40 | return true; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Launcher/MiscHelper.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace Launcher 6 | { 7 | using System; 8 | using System.Linq; 9 | 10 | /// 11 | /// A helper class containing misc functions. 12 | /// 13 | public static class MiscHelper 14 | { 15 | /// 16 | /// Utility function that returns randomly generated string. 17 | /// 18 | /// randomly generated string. 19 | public static string GenerateRandomString() 20 | { 21 | //more common letters! 22 | const string characters = "qwertyuiopasdfghjklzxcvbnm" + "eioadfc"; 23 | var random = new Random(); 24 | 25 | char GetRandomCharacter() 26 | { 27 | return characters[random.Next(0, characters.Length)]; 28 | } 29 | 30 | string GetWord() 31 | { 32 | return char.ToUpperInvariant(GetRandomCharacter()) + 33 | new string(Enumerable.Range(0, random.Next(5, 10)) 34 | .Select(_ => GetRandomCharacter()) 35 | .ToArray()); 36 | } 37 | 38 | return string.Join(' ', Enumerable.Range(0, random.Next(1, 4)).Select(_ => GetWord())); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Launcher/Program.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace Launcher 6 | { 7 | using System; 8 | using System.Diagnostics; 9 | using System.Threading; 10 | 11 | public static class Program 12 | { 13 | private static int Main(string[] args) 14 | { 15 | if (!GameHelperFinder.TryFindGameHelperExe(out var gameHelperDir, out var gameHelperLoc)) 16 | { 17 | Console.WriteLine($"GameHelper.exe is also not found in {gameHelperDir}"); 18 | Console.ReadKey(); 19 | return 1; 20 | } 21 | 22 | try 23 | { 24 | var isWaiting = false; 25 | if (args.Length == 0) 26 | { 27 | Console.WriteLine("Are you waiting for a new GameHelper release? (yes/no)"); 28 | isWaiting = Console.ReadLine().ToLowerInvariant().StartsWith("y"); 29 | } 30 | 31 | do 32 | { 33 | if (AutoUpdate.UpgradeGameHelper(gameHelperDir)) 34 | { 35 | // Returning because Launcher should auto-restart on exit. 36 | return 0; 37 | } 38 | else if (isWaiting) 39 | { 40 | Console.WriteLine("Didn't find any new version, sleeping for 5 mins...."); 41 | Thread.Sleep(5 * 60 * 1000); 42 | } 43 | } 44 | while (isWaiting); 45 | } 46 | catch (Exception ex) 47 | { 48 | Console.WriteLine($"Failed to upgrade GameHelper due to: {ex}"); 49 | Console.ReadKey(); 50 | } 51 | 52 | try 53 | { 54 | Console.WriteLine("Preparing GameHelper..."); 55 | var newName = MiscHelper.GenerateRandomString(); 56 | TemporaryFileManager.Purge(); 57 | //TODO: if functionality extends, should probably utilize an argument parser, but good for now 58 | if (!LocationValidator.IsGameHelperLocationGood(out var message)) 59 | { 60 | Console.WriteLine(message); 61 | Console.Write("Press any key to ignore this warning."); 62 | Console.ReadLine(); 63 | } 64 | 65 | var gameHelperPath = GameHelperTransformer.TransformGameHelperExecutable(gameHelperDir, gameHelperLoc, newName); 66 | Console.WriteLine($"Starting GameHelper at '{gameHelperPath}'..."); 67 | Process.Start(gameHelperPath); 68 | } 69 | catch (Exception ex) 70 | { 71 | Console.WriteLine($"Failed to launch GameHelper due to: {ex}"); 72 | Console.ReadKey(); 73 | } 74 | 75 | return 0; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Launcher/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Launcher": { 4 | "commandName": "Project", 5 | "commandLineArgs": "-allowPath" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /Launcher/TemporaryFileManager.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) None. All rights reserved. 3 | // 4 | 5 | namespace Launcher 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Reflection; 12 | using Newtonsoft.Json; 13 | 14 | /// 15 | /// A helper class to manage the temporary executables created by the . 16 | /// 17 | public static class TemporaryFileManager 18 | { 19 | private const string StoreFileName = "tempFileLocations.dat"; 20 | 21 | /// 22 | /// Adds the file to the manager. 23 | /// 24 | /// file pathname. 25 | public static void AddFile(string path) 26 | { 27 | var fileList = GetFileList(); 28 | WriteFileList(fileList.Append(Path.GetRelativePath(GetDirectoryPath(), path))); 29 | } 30 | 31 | /// 32 | /// Purge all the files added into the . 33 | /// This includes the files added in the previous executions of . 34 | /// 35 | public static void Purge() 36 | { 37 | var fileList = GetFileList(); 38 | var directoryPath = GetDirectoryPath(); 39 | foreach (var file in fileList.Select(x => Path.Join(directoryPath, x))) 40 | { 41 | try 42 | { 43 | if (File.Exists(file)) 44 | { 45 | File.Delete(file); 46 | } 47 | } 48 | catch (Exception ex) 49 | { 50 | Console.WriteLine(ex.ToString()); 51 | } 52 | } 53 | 54 | WriteFileList(Array.Empty()); 55 | } 56 | 57 | private static IReadOnlyList GetFileList() 58 | { 59 | try 60 | { 61 | var tempFileName = GetFullTemporaryFileName(); 62 | if (!File.Exists(tempFileName)) 63 | { 64 | return Array.Empty(); 65 | } 66 | 67 | var fileContent = File.ReadAllText(tempFileName); 68 | return JsonConvert.DeserializeObject>(fileContent); 69 | } 70 | catch (Exception ex) 71 | { 72 | Console.WriteLine(ex.ToString()); 73 | return Array.Empty(); 74 | } 75 | } 76 | 77 | private static void WriteFileList(IEnumerable list) 78 | { 79 | File.WriteAllText(GetFullTemporaryFileName(), JsonConvert.SerializeObject(list.Distinct())); 80 | } 81 | 82 | private static string GetFullTemporaryFileName() 83 | { 84 | return Path.Join(GetDirectoryPath(), StoreFileName); 85 | } 86 | 87 | private static string GetDirectoryPath() 88 | { 89 | var currentProcessPath = Assembly.GetExecutingAssembly().Location; 90 | return Path.GetDirectoryName(currentProcessPath); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Launcher/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 59 | 60 | 61 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /PreloadAlert/PreloadAlert.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | Library 6 | true 7 | 8 | 9 | 10 | x64 11 | 12 | 13 | 14 | x64 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | false 24 | false 25 | 26 | 27 | 28 | 29 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /PreloadAlert/PreloadSettings.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace PreloadAlert 6 | { 7 | using System.Numerics; 8 | using GameHelper.Plugin; 9 | 10 | /// 11 | /// Preload GUI settings. 12 | /// 13 | public sealed class PreloadSettings : IPSettings 14 | { 15 | /// 16 | /// Background color of the preload alert window. 17 | /// 18 | public Vector4 BackgroundColor = new(Vector3.Zero, 0.8f); 19 | 20 | /// 21 | /// Gets a value indicating whether to hide the Ui when not in the game or game in background. 22 | /// 23 | public bool EnableHideUi = false; 24 | 25 | /// 26 | /// Gets a value indicating whether the preload alert window should hide when in town/hideout. 27 | /// 28 | public bool HideWhenInTownOrHideout = false; 29 | 30 | /// 31 | /// Gets a value indicating whether the preload alert window should hide when empty. 32 | /// 33 | public bool HideWindowWhenEmpty = false; 34 | 35 | /// 36 | /// Gets a value indicating whether the preload alert window is locked or not. 37 | /// 38 | public bool Locked = false; 39 | 40 | /// 41 | /// Position of the preload alert window. 42 | /// 43 | public Vector2 Pos = Vector2.Zero; 44 | 45 | /// 46 | /// Size of the preload alert window. 47 | /// 48 | public Vector2 Size = Vector2.Zero; 49 | } 50 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GameOverlay 2 | 3 | No support will be given for this project, that said feel free to fork and do whatever with the codebase as per the original authors wishes. 4 | 5 | For a more advanced tool, check out ExileAPI. 6 | -------------------------------------------------------------------------------- /Radar/Helper.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace Radar 6 | { 7 | using System; 8 | using System.Numerics; 9 | 10 | /// 11 | /// Contains the helper functions. 12 | /// 13 | public static class Helper 14 | { 15 | /// 16 | /// Map rotation in Radian format. 17 | /// 18 | public static readonly double CameraAngle = 38.7 * Math.PI / 180; 19 | private static double diagonalLength = 0x00; 20 | private static float scale = 0.5f; 21 | private static float cos = 0x00; 22 | private static float sin = 0x00; 23 | 24 | /// 25 | /// Sets the diagonal length of the Mini/Large Map UiElement, 26 | /// depending on what's visible. 27 | /// 28 | public static double DiagonalLength 29 | { 30 | private get 31 | { 32 | return diagonalLength; 33 | } 34 | 35 | set 36 | { 37 | if (value > 0 && value != diagonalLength) 38 | { 39 | diagonalLength = value; 40 | UpdateCosSin(); 41 | } 42 | } 43 | } 44 | 45 | /// 46 | /// Sets the scale of the Mini/Large Map, depending on what's visible. 47 | /// 48 | public static float Scale 49 | { 50 | private get 51 | { 52 | return scale; 53 | } 54 | 55 | set 56 | { 57 | if (value > 0 && value != scale) 58 | { 59 | scale = value; 60 | UpdateCosSin(); 61 | } 62 | } 63 | } 64 | 65 | /// 66 | /// Converts Entity to Player delta w.r.t Grid Postion 67 | /// to the Minimap pixel location Delta. 68 | /// 69 | /// 70 | /// Grid postion delta between player and the entity to draw. 71 | /// This is due to the fact that player always remains at center of the mini/large, 72 | /// if we ignore the map shifting feature. 73 | /// 74 | /// 75 | /// Terrain level difference between player and entity. 76 | /// 77 | /// nothing. 78 | public static Vector2 DeltaInWorldToMapDelta(Vector2 delta, float deltaZ) 79 | { 80 | // WorldPosition distance between 2 points 81 | // divide it by GridPosition distance between 2 points. 82 | // Rounded to 2 decimal points. 83 | deltaZ /= 10.87f; 84 | return new Vector2((delta.X - delta.Y) * cos, (deltaZ - (delta.X + delta.Y)) * sin); 85 | } 86 | 87 | private static void UpdateCosSin() 88 | { 89 | // Magic number that works with diagnonal length. 90 | float mapScale = 240f / Scale; 91 | cos = (float)(DiagonalLength * Math.Cos(CameraAngle) / mapScale); 92 | sin = (float)(DiagonalLength * Math.Sin(CameraAngle) / mapScale); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Radar/Radar.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Library 5 | net5.0 6 | true 7 | 8 | 9 | 10 | x64 11 | 12 | 13 | 14 | x64 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | false 29 | false 30 | 31 | 32 | 33 | 34 | 35 | PreserveNewest 36 | 37 | 38 | PreserveNewest 39 | 40 | 41 | 42 | 43 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Radar/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BanditTech/GameOverlay/bc73cedc0b7e362b3007c93decede42b9ca6d635/Radar/icons.png -------------------------------------------------------------------------------- /SamplePluginTemplate/Changeme/Changeme.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | Library 6 | true 7 | 8 | 9 | 10 | x64 11 | 12 | 13 | 14 | x64 15 | 16 | 17 | 18 | 19 | 20 | all 21 | runtime; build; native; contentfiles; analyzers; buildtransitive 22 | 23 | 24 | 25 | 26 | 27 | false 28 | false 29 | 30 | 31 | 32 | 33 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /SamplePluginTemplate/Changeme/ChangemeCore.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace Changeme 6 | { 7 | using GameHelper.Plugin; 8 | 9 | /// 10 | /// plugin. 11 | /// 12 | public sealed class ChangemeCore : PCore 13 | { 14 | /// 15 | public override void DrawSettings() 16 | { 17 | } 18 | 19 | /// 20 | public override void DrawUI() 21 | { 22 | } 23 | 24 | /// 25 | public override void OnDisable() 26 | { 27 | } 28 | 29 | /// 30 | public override void OnEnable() 31 | { 32 | } 33 | 34 | /// 35 | public override void SaveSettings() 36 | { 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SamplePluginTemplate/Changeme/ChangemeSettings.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) PlaceholderCompany. All rights reserved. 3 | // 4 | 5 | namespace Changeme 6 | { 7 | using GameHelper.Plugin; 8 | 9 | /// 10 | /// plugin settings class. 11 | /// 12 | public sealed class ChangemeSettings : IPSettings 13 | { 14 | } 15 | } 16 | --------------------------------------------------------------------------------