├── .gitignore ├── Eggstensions ├── .editorconfig ├── Eggstensions.sln └── Eggstensions │ ├── A │ ├── AccumulatingValueModifierEffect.cs │ ├── ActiveEffect.cs │ ├── Actor.cs │ ├── ActorMagicCaster.cs │ ├── ActorProcess.cs │ ├── ActorValueOwner.cs │ └── ArrowProjectile.cs │ ├── AddressLibrary.cs │ ├── Assembly.cs │ ├── B │ ├── BGSEntryPointFunctionData.cs │ ├── BGSEntryPointFunctionDataSpellItem.cs │ ├── BGSEntryPointPerkEntry.cs │ ├── BGSMovementType.cs │ ├── BGSPerkEntry.cs │ ├── BSAttachTechniques.cs │ ├── BSFixedString.cs │ ├── BSHandleRefObject.cs │ ├── BSPointerHandle.cs │ ├── BSTArray.cs │ ├── BSTEventSink.cs │ ├── BSTEventSource.cs │ └── bhkWorld.cs │ ├── C │ └── Color.cs │ ├── Context.cs │ ├── DNNE.cs │ ├── E │ ├── Effect.cs │ ├── EffectSetting.cs │ ├── EnchantmentItem.cs │ └── ExtraDataList.cs │ ├── Eggstensions.projitems │ ├── Eggstensions.shproj │ ├── Events.cs │ ├── ExtensionMethods.cs │ ├── F │ └── FindMaxMagnitudeVisitor.cs │ ├── H │ └── HandleEntryPointVisitor.cs │ ├── I │ ├── IAnimationGraphManagerHolder.cs │ ├── InitTESThread.cs │ ├── InventoryChanges.cs │ └── InventoryEntryData.cs │ ├── Log.cs │ ├── M │ ├── MagicCaster.cs │ ├── MagicItem.cs │ ├── MagicTarget.cs │ ├── MissileProjectile.cs │ └── ModelReferenceEffect.cs │ ├── Main.cs │ ├── Math.cs │ ├── Memory.cs │ ├── N │ ├── NiAVObject.cs │ ├── NiNode.cs │ ├── NiObject.cs │ ├── NiPoint3.cs │ ├── NiPointer.cs │ └── NiRefObject.cs │ ├── Offsets.cs │ ├── P │ ├── PlayerCharacter.cs │ └── Projectile.cs │ ├── R │ ├── RefAttachTechniqueInput.cs │ ├── ReferenceEffect.cs │ └── ReferenceEffectController.cs │ ├── S │ ├── ScriptEventSourceHolder.cs │ ├── Setting.cs │ ├── SettingT.cs │ └── SpellItem.cs │ ├── SKSE.cs │ ├── T │ ├── TESActorBase.cs │ ├── TESAmmo.cs │ ├── TESBoundObject.cs │ ├── TESDataHandler.cs │ ├── TESForm.cs │ ├── TESFullName.cs │ ├── TESHitEvent.cs │ ├── TESNPC.cs │ ├── TESObjectARMO.cs │ ├── TESObjectREFR.cs │ ├── TESObjectWEAP.cs │ ├── TESQuest.cs │ └── TESRace.cs │ ├── Trampoline.cs │ ├── U │ └── UI.cs │ ├── UnmanagedArray.cs │ ├── UnmanagedObject.cs │ ├── UnmanagedType.cs │ ├── V │ └── ValueModifierEffect.cs │ └── VirtualObject.cs ├── README.md └── ScrambledBugs ├── .editorconfig ├── ScrambledBugs.json ├── ScrambledBugs.sln └── ScrambledBugs ├── Fixes ├── ActorValuePercentage.cs ├── ApplySpellPerkEntryPoints │ └── Arrows.cs ├── HarvestedFlags.cs ├── HitEffectRaceCondition.cs ├── MagicEffectConditions.cs ├── MagicEffectFlags.cs ├── ModArmorWeightPerkEntryPoint.cs ├── QuickShot.cs ├── SpeedMultUpdates.cs ├── TerrainDecals.cs ├── TrainingMenuText.cs └── WeaponCharge.cs ├── Offsets.cs ├── Patches ├── AccumulatingMagnitude.cs ├── AlreadyCaughtPickpocketing.cs ├── ApplySpellPerkEntryPoints │ ├── CastSpells.cs │ └── MultipleSpells.cs ├── AttachHitEffectArt.cs ├── EquipBestAmmo.cs ├── LeveledCharacters.cs ├── LockpickingExperience.cs ├── MultipleHitEffects.cs ├── PausedGameHitEffects.cs ├── PowerAttackStamina.cs ├── ReflectDamage.cs ├── TeammateDifficulty.cs └── UnderfilledSoulGems.cs ├── Patterns.cs ├── Plugin.cs ├── ScrambledBugs.csproj └── Settings.cs /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.vspscc 94 | *.vssscc 95 | .builds 96 | *.pidb 97 | *.svclog 98 | *.scc 99 | 100 | # Chutzpah Test files 101 | _Chutzpah* 102 | 103 | # Visual C++ cache files 104 | ipch/ 105 | *.aps 106 | *.ncb 107 | *.opendb 108 | *.opensdf 109 | *.sdf 110 | *.cachefile 111 | *.VC.db 112 | *.VC.VC.opendb 113 | 114 | # Visual Studio profiler 115 | *.psess 116 | *.vsp 117 | *.vspx 118 | *.sap 119 | 120 | # Visual Studio Trace Files 121 | *.e2e 122 | 123 | # TFS 2012 Local Workspace 124 | $tf/ 125 | 126 | # Guidance Automation Toolkit 127 | *.gpState 128 | 129 | # ReSharper is a .NET coding add-in 130 | _ReSharper*/ 131 | *.[Rr]e[Ss]harper 132 | *.DotSettings.user 133 | 134 | # TeamCity is a build add-in 135 | _TeamCity* 136 | 137 | # DotCover is a Code Coverage Tool 138 | *.dotCover 139 | 140 | # AxoCover is a Code Coverage Tool 141 | .axoCover/* 142 | !.axoCover/settings.json 143 | 144 | # Coverlet is a free, cross platform Code Coverage Tool 145 | coverage*.json 146 | coverage*.xml 147 | coverage*.info 148 | 149 | # Visual Studio code coverage results 150 | *.coverage 151 | *.coveragexml 152 | 153 | # NCrunch 154 | _NCrunch_* 155 | .*crunch*.local.xml 156 | nCrunchTemp_* 157 | 158 | # MightyMoose 159 | *.mm.* 160 | AutoTest.Net/ 161 | 162 | # Web workbench (sass) 163 | .sass-cache/ 164 | 165 | # Installshield output folder 166 | [Ee]xpress/ 167 | 168 | # DocProject is a documentation generator add-in 169 | DocProject/buildhelp/ 170 | DocProject/Help/*.HxT 171 | DocProject/Help/*.HxC 172 | DocProject/Help/*.hhc 173 | DocProject/Help/*.hhk 174 | DocProject/Help/*.hhp 175 | DocProject/Help/Html2 176 | DocProject/Help/html 177 | 178 | # Click-Once directory 179 | publish/ 180 | 181 | # Publish Web Output 182 | *.[Pp]ublish.xml 183 | *.azurePubxml 184 | # Note: Comment the next line if you want to checkin your web deploy settings, 185 | # but database connection strings (with potential passwords) will be unencrypted 186 | *.pubxml 187 | *.publishproj 188 | 189 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 190 | # checkin your Azure Web App publish settings, but sensitive information contained 191 | # in these scripts will be unencrypted 192 | PublishScripts/ 193 | 194 | # NuGet Packages 195 | *.nupkg 196 | # NuGet Symbol Packages 197 | *.snupkg 198 | # The packages folder can be ignored because of Package Restore 199 | **/[Pp]ackages/* 200 | # except build/, which is used as an MSBuild target. 201 | !**/[Pp]ackages/build/ 202 | # Uncomment if necessary however generally it will be regenerated when needed 203 | #!**/[Pp]ackages/repositories.config 204 | # NuGet v3's project.json files produces more ignorable files 205 | *.nuget.props 206 | *.nuget.targets 207 | 208 | # Microsoft Azure Build Output 209 | csx/ 210 | *.build.csdef 211 | 212 | # Microsoft Azure Emulator 213 | ecf/ 214 | rcf/ 215 | 216 | # Windows Store app package directories and files 217 | AppPackages/ 218 | BundleArtifacts/ 219 | Package.StoreAssociation.xml 220 | _pkginfo.txt 221 | *.appx 222 | *.appxbundle 223 | *.appxupload 224 | 225 | # Visual Studio cache files 226 | # files ending in .cache can be ignored 227 | *.[Cc]ache 228 | # but keep track of directories ending in .cache 229 | !?*.[Cc]ache/ 230 | 231 | # Others 232 | ClientBin/ 233 | ~$* 234 | *~ 235 | *.dbmdl 236 | *.dbproj.schemaview 237 | *.jfm 238 | *.pfx 239 | *.publishsettings 240 | orleans.codegen.cs 241 | 242 | # Including strong name files can present a security risk 243 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 244 | #*.snk 245 | 246 | # Since there are multiple workflows, uncomment next line to ignore bower_components 247 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 248 | #bower_components/ 249 | 250 | # RIA/Silverlight projects 251 | Generated_Code/ 252 | 253 | # Backup & report files from converting an old project file 254 | # to a newer Visual Studio version. Backup files are not needed, 255 | # because we have git ;-) 256 | _UpgradeReport_Files/ 257 | Backup*/ 258 | UpgradeLog*.XML 259 | UpgradeLog*.htm 260 | ServiceFabricBackup/ 261 | *.rptproj.bak 262 | 263 | # SQL Server files 264 | *.mdf 265 | *.ldf 266 | *.ndf 267 | 268 | # Business Intelligence projects 269 | *.rdl.data 270 | *.bim.layout 271 | *.bim_*.settings 272 | *.rptproj.rsuser 273 | *- [Bb]ackup.rdl 274 | *- [Bb]ackup ([0-9]).rdl 275 | *- [Bb]ackup ([0-9][0-9]).rdl 276 | 277 | # Microsoft Fakes 278 | FakesAssemblies/ 279 | 280 | # GhostDoc plugin setting file 281 | *.GhostDoc.xml 282 | 283 | # Node.js Tools for Visual Studio 284 | .ntvs_analysis.dat 285 | node_modules/ 286 | 287 | # Visual Studio 6 build log 288 | *.plg 289 | 290 | # Visual Studio 6 workspace options file 291 | *.opt 292 | 293 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 294 | *.vbw 295 | 296 | # Visual Studio LightSwitch build output 297 | **/*.HTMLClient/GeneratedArtifacts 298 | **/*.DesktopClient/GeneratedArtifacts 299 | **/*.DesktopClient/ModelManifest.xml 300 | **/*.Server/GeneratedArtifacts 301 | **/*.Server/ModelManifest.xml 302 | _Pvt_Extensions 303 | 304 | # Paket dependency manager 305 | .paket/paket.exe 306 | paket-files/ 307 | 308 | # FAKE - F# Make 309 | .fake/ 310 | 311 | # CodeRush personal settings 312 | .cr/personal 313 | 314 | # Python Tools for Visual Studio (PTVS) 315 | __pycache__/ 316 | *.pyc 317 | 318 | # Cake - Uncomment if you are using it 319 | # tools/** 320 | # !tools/packages.config 321 | 322 | # Tabs Studio 323 | *.tss 324 | 325 | # Telerik's JustMock configuration file 326 | *.jmconfig 327 | 328 | # BizTalk build output 329 | *.btp.cs 330 | *.btm.cs 331 | *.odx.cs 332 | *.xsd.cs 333 | 334 | # OpenCover UI analysis results 335 | OpenCover/ 336 | 337 | # Azure Stream Analytics local run output 338 | ASALocalRun/ 339 | 340 | # MSBuild Binary and Structured Log 341 | *.binlog 342 | 343 | # NVidia Nsight GPU debugger configuration file 344 | *.nvuser 345 | 346 | # MFractors (Xamarin productivity tool) working folder 347 | .mfractor/ 348 | 349 | # Local History for Visual Studio 350 | .localhistory/ 351 | 352 | # BeatPulse healthcheck temp database 353 | healthchecksdb 354 | 355 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 356 | MigrationBackup/ 357 | 358 | # Ionide (cross platform F# VS Code tools) working folder 359 | .ionide/ 360 | 361 | # Fody - auto-generated XML schema 362 | FodyWeavers.xsd 363 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31205.134 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Eggstensions", "Eggstensions\Eggstensions.shproj", "{740EFF05-9743-47CE-B6EA-09584EAF1EDF}" 7 | EndProject 8 | Global 9 | GlobalSection(SharedMSBuildProjectFiles) = preSolution 10 | Eggstensions\Eggstensions.projitems*{740eff05-9743-47ce-b6ea-09584eaf1edf}*SharedItemsImports = 13 11 | EndGlobalSection 12 | GlobalSection(SolutionProperties) = preSolution 13 | HideSolutionNode = FALSE 14 | EndGlobalSection 15 | GlobalSection(ExtensibilityGlobals) = postSolution 16 | SolutionGuid = {B6644951-15EA-4B0B-869D-8673709E1D89} 17 | EndGlobalSection 18 | EndGlobal 19 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/A/AccumulatingValueModifierEffect.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IAccumulatingValueModifierEffect : IValueModifierEffect 4 | { 5 | } 6 | 7 | public struct AccumulatingValueModifierEffect : IAccumulatingValueModifierEffect 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class IAccumulatingValueModifierEffect 16 | { 17 | // Field 18 | static public System.Single CurrentMagnitude(this ref TAccumulatingValueModifierEffect accumulatingValueModifierEffect) 19 | where TAccumulatingValueModifierEffect : unmanaged, Eggstensions.IAccumulatingValueModifierEffect 20 | { 21 | return *(System.Single*)accumulatingValueModifierEffect.AddByteOffset(0x98); 22 | } 23 | 24 | static public System.Single MaximumMagnitude(this ref TAccumulatingValueModifierEffect accumulatingValueModifierEffect) 25 | where TAccumulatingValueModifierEffect : unmanaged, Eggstensions.IAccumulatingValueModifierEffect 26 | { 27 | return *(System.Single*)accumulatingValueModifierEffect.AddByteOffset(0x9C); 28 | } 29 | 30 | static public System.Single HoldDuration(this ref TAccumulatingValueModifierEffect accumulatingValueModifierEffect) 31 | where TAccumulatingValueModifierEffect : unmanaged, Eggstensions.IAccumulatingValueModifierEffect 32 | { 33 | return *(System.Single*)accumulatingValueModifierEffect.AddByteOffset(0xA0); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/A/ActiveEffect.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | [System.Flags] 4 | public enum ActiveEffectFlags : System.UInt32 5 | { 6 | NoHitShader = 1U << 1, 7 | NoHitEffectArt = 1U << 2, 8 | NoInitialFlare = 1U << 4, 9 | ApplyingVisualEffects = 1U << 5, 10 | ApplyingSounds = 1U << 6, 11 | HasConditions = 1U << 7, 12 | Recover = 1U << 9, 13 | DualCasting = 1U << 12, 14 | Inactive = 1U << 15, 15 | AppliedEffects = 1U << 16, 16 | RemovedEffects = 1U << 17, 17 | Dispelled = 1U << 18, 18 | WornOff = 1U << 31 19 | } 20 | 21 | 22 | 23 | public interface IActiveEffect : IVirtualObject 24 | { 25 | } 26 | 27 | public struct ActiveEffect : IActiveEffect 28 | { 29 | } 30 | 31 | 32 | 33 | namespace ExtensionMethods 34 | { 35 | unsafe static public class IActiveEffect 36 | { 37 | // Field 38 | static public BSPointerHandle Caster(this ref TActiveEffect activeEffect) 39 | where TActiveEffect : unmanaged, Eggstensions.IActiveEffect 40 | { 41 | return *(BSPointerHandle*)activeEffect.AddByteOffset(0x34); // Actor 42 | } 43 | 44 | static public MagicItem* Spell(this ref TActiveEffect activeEffect) 45 | where TActiveEffect : unmanaged, Eggstensions.IActiveEffect 46 | { 47 | return *(MagicItem**)activeEffect.AddByteOffset(0x40); 48 | } 49 | 50 | static public Effect* Effect(this ref TActiveEffect activeEffect) 51 | where TActiveEffect : unmanaged, Eggstensions.IActiveEffect 52 | { 53 | return *(Effect**)activeEffect.AddByteOffset(0x48); 54 | } 55 | 56 | static public MagicTarget* MagicTarget(this ref TActiveEffect activeEffect) 57 | where TActiveEffect : unmanaged, Eggstensions.IActiveEffect 58 | { 59 | return *(MagicTarget**)activeEffect.AddByteOffset(0x50); 60 | } 61 | 62 | static public System.Single ElapsedTime(this ref TActiveEffect activeEffect) 63 | where TActiveEffect : unmanaged, Eggstensions.IActiveEffect 64 | { 65 | return *(System.Single*)activeEffect.AddByteOffset(0x70); 66 | } 67 | 68 | static public System.Single Duration(this ref TActiveEffect activeEffect) 69 | where TActiveEffect : unmanaged, Eggstensions.IActiveEffect 70 | { 71 | return *(System.Single*)activeEffect.AddByteOffset(0x74); 72 | } 73 | 74 | static public void Duration(this ref TActiveEffect activeEffect, System.Single duration) 75 | where TActiveEffect : unmanaged, Eggstensions.IActiveEffect 76 | { 77 | *(System.Single*)activeEffect.AddByteOffset(0x74) = duration; 78 | } 79 | 80 | static public System.Single Magnitude(this ref TActiveEffect activeEffect) 81 | where TActiveEffect : unmanaged, Eggstensions.IActiveEffect 82 | { 83 | return *(System.Single*)activeEffect.AddByteOffset(0x78); 84 | } 85 | 86 | static public void Magnitude(this ref TActiveEffect activeEffect, System.Single magnitude) 87 | where TActiveEffect : unmanaged, Eggstensions.IActiveEffect 88 | { 89 | *(System.Single*)activeEffect.AddByteOffset(0x78) = magnitude; 90 | } 91 | 92 | static public ActiveEffectFlags Flags(this ref TActiveEffect activeEffect) 93 | where TActiveEffect : unmanaged, Eggstensions.IActiveEffect 94 | { 95 | return (ActiveEffectFlags)(*(System.UInt32*)activeEffect.AddByteOffset(0x7C)); 96 | } 97 | 98 | static public CastingSource CastingSource(this ref TActiveEffect activeEffect) 99 | where TActiveEffect : unmanaged, Eggstensions.IActiveEffect 100 | { 101 | return (CastingSource)(*(System.Int32*)activeEffect.AddByteOffset(0x88)); 102 | } 103 | 104 | 105 | 106 | // Member 107 | static public void Dispel(this ref TActiveEffect activeEffect, System.Boolean force) 108 | where TActiveEffect : unmanaged, Eggstensions.IActiveEffect 109 | { 110 | var dispel = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.ActiveEffect.Dispel; 111 | 112 | Dispel(activeEffect.AsPointer(), (System.Byte)(force ? 1 : 0)); 113 | 114 | 115 | 116 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 117 | void Dispel(TActiveEffect* activeEffect, System.Byte force) 118 | { 119 | dispel(activeEffect, force); 120 | } 121 | } 122 | 123 | static public System.Single GetCurrentMagnitude(this ref TActiveEffect activeEffect) 124 | where TActiveEffect : unmanaged, Eggstensions.IActiveEffect 125 | { 126 | var getCurrentMagnitude = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.ActiveEffect.GetCurrentMagnitude; 127 | 128 | return GetCurrentMagnitude(activeEffect.AsPointer()); 129 | 130 | 131 | 132 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 133 | System.Single GetCurrentMagnitude(TActiveEffect* activeEffect) 134 | { 135 | return getCurrentMagnitude(activeEffect); 136 | } 137 | } 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/A/Actor.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public enum EquipType : System.Int32 4 | { 5 | LeftHand = 0, 6 | RightHand = 1, 7 | } 8 | 9 | 10 | 11 | public interface IActor : ITESObjectREFR 12 | { 13 | } 14 | 15 | public struct Actor : IActor 16 | { 17 | } 18 | 19 | 20 | 21 | namespace ExtensionMethods 22 | { 23 | unsafe static public class IActor 24 | { 25 | // Inheritance 26 | static public MagicTarget* MagicTarget(this ref TActor actor) 27 | where TActor : unmanaged, Eggstensions.IActor 28 | { 29 | return (MagicTarget*)actor.AddByteOffset(0x98); 30 | } 31 | 32 | static public ActorValueOwner* ActorValueOwner(this ref TActor actor) 33 | where TActor : unmanaged, Eggstensions.IActor 34 | { 35 | return (ActorValueOwner*)actor.AddByteOffset(0xB0); 36 | } 37 | 38 | 39 | 40 | // Field 41 | static public ActorProcess* CurrentProcess(this ref TActor actor) 42 | where TActor : unmanaged, Eggstensions.IActor 43 | { 44 | return *(ActorProcess**)actor.AddByteOffset(0xF0); 45 | } 46 | 47 | 48 | 49 | // Virtual 50 | static public MagicCaster* GetMagicCaster(this ref TActor actor, CastingSource castingSource) 51 | where TActor : unmanaged, Eggstensions.IActor 52 | { 53 | var getMagicCaster = (delegate* unmanaged[Cdecl])actor.VirtualFunction(0x5C); 54 | 55 | return GetMagicCaster(actor.AsPointer(), (System.Int32)castingSource); 56 | 57 | 58 | 59 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 60 | MagicCaster* GetMagicCaster(TActor* actor, System.Int32 castingSource) 61 | { 62 | return getMagicCaster(actor, castingSource); 63 | } 64 | } 65 | 66 | 67 | 68 | // Member 69 | static public System.Boolean AddSpell(this ref TActor actor, TSpellItem* spell) 70 | where TActor : unmanaged, Eggstensions.IActor 71 | where TSpellItem : unmanaged, Eggstensions.ISpellItem 72 | { 73 | var addSpell = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.Actor.AddSpell; 74 | 75 | return AddSpell(actor.AsPointer(), spell) != 0; 76 | 77 | 78 | 79 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 80 | System.Byte AddSpell(TActor* actor, TSpellItem* spell) 81 | { 82 | return addSpell(actor, spell); 83 | } 84 | } 85 | 86 | static public System.Single GetActorValueModifier(this ref TActor actor, ActorValueModifier actorValueModifier, ActorValue actorValue) 87 | where TActor : unmanaged, Eggstensions.IActor 88 | { 89 | var getActorValueModifier = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.Actor.GetActorValueModifier; 90 | 91 | return GetActorValueModifier(actor.AsPointer(), (System.Int32)actorValueModifier, (System.Int32)actorValue); 92 | 93 | 94 | 95 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 96 | System.Single GetActorValueModifier(TActor* actor, System.Int32 actorValueModifier, System.Int32 actorValue) 97 | { 98 | return getActorValueModifier(actor, actorValueModifier, actorValue); 99 | } 100 | } 101 | 102 | static public TESObjectWEAP* GetEquippedWeapon(this ref TActor actor, System.Boolean leftHand) 103 | where TActor : unmanaged, Eggstensions.IActor 104 | { 105 | var getEquippedWeapon = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.Actor.GetEquippedWeapon; 106 | 107 | return GetEquippedWeapon(actor.AsPointer(), (System.Byte)(leftHand ? 1 : 0)); 108 | 109 | 110 | 111 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 112 | TESObjectWEAP* GetEquippedWeapon(TActor* actor, System.Byte leftHand) 113 | { 114 | return getEquippedWeapon(actor, leftHand); 115 | } 116 | } 117 | 118 | static public System.Single GetMaximumWardPower(this ref TActor actor) 119 | where TActor : unmanaged, Eggstensions.IActor 120 | { 121 | var getMaximumWardPower = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.Actor.GetMaximumWardPower; 122 | 123 | return GetMaximumWardPower(actor.AsPointer()); 124 | 125 | 126 | 127 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 128 | System.Single GetMaximumWardPower(TActor* actor) 129 | { 130 | return getMaximumWardPower(actor); 131 | } 132 | } 133 | 134 | static public System.Boolean GetMovementActor(this ref TActor actor, NiPointer* movementActor) 135 | where TActor : unmanaged, Eggstensions.IActor 136 | { 137 | var getMovementActor = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.Actor.GetMovementActor; 138 | 139 | return GetMovementActor(actor.AsPointer(), movementActor) != 0; 140 | 141 | 142 | 143 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 144 | System.Byte GetMovementActor(TActor* actor, NiPointer* movementActor) 145 | { 146 | return getMovementActor(actor, movementActor); 147 | } 148 | } 149 | 150 | static public void RemoveActorValueModifiers(this ref TActor actor, ActorValue actorValue) 151 | where TActor : unmanaged, Eggstensions.IActor 152 | { 153 | var removeActorValueModifiers = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.Actor.RemoveActorValueModifiers; 154 | 155 | RemoveActorValueModifiers(actor.AsPointer(), (System.Int32)actorValue); 156 | 157 | 158 | 159 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 160 | void RemoveActorValueModifiers(TActor* actor, System.Int32 actorValue) 161 | { 162 | removeActorValueModifiers(actor, actorValue); 163 | } 164 | } 165 | 166 | static public void RevertSelectedSpell(this ref TActor actor, EquipType equipType, TMagicItem* magicItem) 167 | where TActor : unmanaged, Eggstensions.IActor 168 | where TMagicItem : unmanaged, Eggstensions.IMagicItem 169 | { 170 | var revertSelectedSpell = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.Actor.RevertSelectedSpell; 171 | 172 | RevertSelectedSpell(actor.AsPointer(), (System.Int32)equipType, magicItem); 173 | 174 | 175 | 176 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 177 | void RevertSelectedSpell(TActor* actor, System.Int32 equipType, TMagicItem* magicItem) 178 | { 179 | revertSelectedSpell(actor, equipType, magicItem); 180 | } 181 | } 182 | 183 | static public void SetMaximumWardPower(this ref TActor actor, System.Single maximumWardPower) 184 | where TActor : unmanaged, Eggstensions.IActor 185 | { 186 | var setMaximumWardPower = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.Actor.SetMaximumWardPower; 187 | 188 | SetMaximumWardPower(actor.AsPointer(), maximumWardPower); 189 | 190 | 191 | 192 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 193 | void SetMaximumWardPower(TActor* actor, System.Single maximumWardPower) 194 | { 195 | setMaximumWardPower(actor, maximumWardPower); 196 | } 197 | } 198 | 199 | static public void UpdateMovementSpeed(this ref TActor actor) 200 | where TActor : unmanaged, Eggstensions.IActor 201 | { 202 | var updateMovementSpeed = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.Actor.UpdateMovementSpeed; 203 | 204 | UpdateMovementSpeed(actor.AsPointer()); 205 | 206 | 207 | 208 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 209 | void UpdateMovementSpeed(TActor* actor) 210 | { 211 | updateMovementSpeed(actor); 212 | } 213 | } 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/A/ActorMagicCaster.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IActorMagicCaster : IMagicCaster 4 | { 5 | } 6 | 7 | public struct ActorMagicCaster : IActorMagicCaster 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/A/ActorProcess.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IActorProcess 4 | { 5 | } 6 | 7 | public struct ActorProcess : IActorProcess 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/A/ActorValueOwner.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public enum ActorValue : System.Int32 4 | { 5 | None = -1, 6 | Health = 24, 7 | Magicka = 25, 8 | Stamina = 26, 9 | SpeedMult = 30, 10 | WardPower = 63, 11 | RightItemCharge = 64, 12 | LeftItemCharge = 82 13 | } 14 | 15 | public enum ActorValueModifier : System.Int32 16 | { 17 | Permanent = 0, 18 | Temporary = 1, 19 | Damage = 2 20 | } 21 | 22 | 23 | 24 | public interface IActorValueOwner : IVirtualObject 25 | { 26 | } 27 | 28 | public struct ActorValueOwner : IActorValueOwner 29 | { 30 | } 31 | 32 | 33 | 34 | namespace ExtensionMethods 35 | { 36 | unsafe static public class IActorValueOwner 37 | { 38 | // Virtual 39 | static public System.Single GetActorValue(this ref TActorValueOwner actorValueOwner, ActorValue actorValue) 40 | where TActorValueOwner : unmanaged, Eggstensions.IActorValueOwner 41 | { 42 | var getActorValue = (delegate* unmanaged[Cdecl])actorValueOwner.VirtualFunction(0x1); 43 | 44 | return GetActorValue(actorValueOwner.AsPointer(), (System.Int32)actorValue); 45 | 46 | 47 | 48 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 49 | System.Single GetActorValue(TActorValueOwner* actorValueOwner, System.Int32 actorValue) 50 | { 51 | return getActorValue(actorValueOwner, actorValue); 52 | } 53 | } 54 | 55 | static public System.Single GetPermanentActorValue(this ref TActorValueOwner actorValueOwner, ActorValue actorValue) 56 | where TActorValueOwner : unmanaged, Eggstensions.IActorValueOwner 57 | { 58 | var getPermanentActorValue = (delegate* unmanaged[Cdecl])actorValueOwner.VirtualFunction(0x2); 59 | 60 | return GetPermanentActorValue(actorValueOwner.AsPointer(), (System.Int32)actorValue); 61 | 62 | 63 | 64 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 65 | System.Single GetPermanentActorValue(TActorValueOwner* actorValueOwner, System.Int32 actorValue) 66 | { 67 | return getPermanentActorValue(actorValueOwner, actorValue); 68 | } 69 | } 70 | 71 | static public void RestoreActorValue(this ref TActorValueOwner actorValueOwner, ActorValueModifier actorValueModifier, ActorValue actorValue, System.Single value) 72 | where TActorValueOwner : unmanaged, Eggstensions.IActorValueOwner 73 | { 74 | var restoreActorValue = (delegate* unmanaged[Cdecl])actorValueOwner.VirtualFunction(0x6); 75 | 76 | RestoreActorValue(actorValueOwner.AsPointer(), (System.Int32)actorValueModifier, (System.Int32)actorValue, value); 77 | 78 | 79 | 80 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 81 | void RestoreActorValue(TActorValueOwner* actorValueOwner, System.Int32 actorValueModifier, System.Int32 actorValue, System.Single value) 82 | { 83 | restoreActorValue(actorValueOwner, actorValueModifier, actorValue, value); 84 | } 85 | } 86 | 87 | static public void SetActorValue(this ref TActorValueOwner actorValueOwner, ActorValue actorValue, System.Single value) 88 | where TActorValueOwner : unmanaged, Eggstensions.IActorValueOwner 89 | { 90 | var setActorValue = (delegate* unmanaged[Cdecl])actorValueOwner.VirtualFunction(0x7); 91 | 92 | SetActorValue(actorValueOwner.AsPointer(), (System.Int32)actorValue, value); 93 | 94 | 95 | 96 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 97 | void SetActorValue(TActorValueOwner* actorValueOwner, System.Int32 actorValue, System.Single value) 98 | { 99 | setActorValue(actorValueOwner, actorValue, value); 100 | } 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/A/ArrowProjectile.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IArrowProjectile : IMissileProjectile 4 | { 5 | } 6 | 7 | public struct ArrowProjectile : IArrowProjectile 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/B/BGSEntryPointFunctionData.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public enum EntryPointFunctionDataType : System.Int32 4 | { 5 | Invalid = 0, 6 | OneValue = 1, 7 | TwoValue = 2, 8 | LeveledList = 3, 9 | ActivateChoice = 4, 10 | SpellItem = 5, 11 | BooleanGraphVariable = 6, 12 | Text = 7 13 | } 14 | 15 | 16 | 17 | public interface IBGSEntryPointFunctionData : IVirtualObject 18 | { 19 | } 20 | 21 | public struct BGSEntryPointFunctionData : IBGSEntryPointFunctionData 22 | { 23 | } 24 | 25 | 26 | 27 | namespace ExtensionMethods 28 | { 29 | unsafe static public class IBGSEntryPointFunctionData 30 | { 31 | // Virtual 32 | static public EntryPointFunctionDataType GetDataType(this ref TBGSEntryPointFunctionData entryPointFunctionData) 33 | where TBGSEntryPointFunctionData : unmanaged, Eggstensions.IBGSEntryPointFunctionData 34 | { 35 | var getDataType = (delegate* unmanaged[Cdecl])entryPointFunctionData.VirtualFunction(0x1); 36 | 37 | return (EntryPointFunctionDataType)GetDataType(entryPointFunctionData.AsPointer()); 38 | 39 | 40 | 41 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 42 | System.Int32 GetDataType(TBGSEntryPointFunctionData* entryPointFunctionData) 43 | { 44 | return getDataType(entryPointFunctionData); 45 | } 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/B/BGSEntryPointFunctionDataSpellItem.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IBGSEntryPointFunctionDataSpellItem : IBGSEntryPointFunctionData 4 | { 5 | } 6 | 7 | public struct BGSEntryPointFunctionDataSpellItem : IBGSEntryPointFunctionDataSpellItem 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class IBGSEntryPointFunctionDataSpellItem 16 | { 17 | // Field 18 | static public SpellItem* Spell(this ref TBGSEntryPointFunctionDataSpellItem entryPointFunctionDataSpellItem) 19 | where TBGSEntryPointFunctionDataSpellItem : unmanaged, Eggstensions.IBGSEntryPointFunctionDataSpellItem 20 | { 21 | return *(SpellItem**)entryPointFunctionDataSpellItem.AddByteOffset(0x8); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/B/BGSEntryPointPerkEntry.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IBGSEntryPointPerkEntry : IBGSPerkEntry 4 | { 5 | } 6 | 7 | unsafe public struct BGSEntryPointPerkEntry 8 | { 9 | // Static 10 | static public void HandleEntryPoints(EntryPoint entryPoint, TActor* perkOwner, void* result1) 11 | where TActor : unmanaged, IActor 12 | { 13 | var handleEntryPoints = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.BGSEntryPointPerkEntry.HandleEntryPoints; 14 | 15 | HandleEntryPoints((System.Int32)entryPoint, perkOwner, result1); 16 | 17 | 18 | 19 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 20 | void HandleEntryPoints(System.Int32 entryPoint, TActor* perkOwner, void* result1) 21 | { 22 | handleEntryPoints(entryPoint, perkOwner, result1); 23 | } 24 | } 25 | 26 | static public void HandleEntryPoints(EntryPoint entryPoint, TActor* perkOwner, void* argument2, void* result1) 27 | where TActor : unmanaged, IActor 28 | { 29 | var handleEntryPoints = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.BGSEntryPointPerkEntry.HandleEntryPoints; 30 | 31 | HandleEntryPoints((System.Int32)entryPoint, perkOwner, argument2, result1); 32 | 33 | 34 | 35 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 36 | void HandleEntryPoints(System.Int32 entryPoint, TActor* perkOwner, void* argument2, void* result1) 37 | { 38 | handleEntryPoints(entryPoint, perkOwner, argument2, result1); 39 | } 40 | } 41 | 42 | static public void HandleEntryPoints(EntryPoint entryPoint, TActor* perkOwner, void* argument2, void* argument3, void* result1) 43 | where TActor : unmanaged, IActor 44 | { 45 | var handleEntryPoints = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.BGSEntryPointPerkEntry.HandleEntryPoints; 46 | 47 | HandleEntryPoints((System.Int32)entryPoint, perkOwner, argument2, argument3, result1); 48 | 49 | 50 | 51 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 52 | void HandleEntryPoints(System.Int32 entryPoint, TActor* perkOwner, void* argument2, void* argument3, void* result1) 53 | { 54 | handleEntryPoints(entryPoint, perkOwner, argument2, argument3, result1); 55 | } 56 | } 57 | } 58 | 59 | 60 | 61 | namespace ExtensionMethods 62 | { 63 | unsafe static public class IBGSEntryPointPerkEntry 64 | { 65 | // Field 66 | static public EntryPoint EntryPoint(this ref TBGSEntryPointPerkEntry entryPointPerkEntry) 67 | where TBGSEntryPointPerkEntry : unmanaged, Eggstensions.IBGSEntryPointPerkEntry 68 | { 69 | return (EntryPoint)(*(System.Byte*)entryPointPerkEntry.AddByteOffset(0x10)); 70 | } 71 | 72 | static public EntryPointFunction Function(this ref TBGSEntryPointPerkEntry entryPointPerkEntry) 73 | where TBGSEntryPointPerkEntry : unmanaged, Eggstensions.IBGSEntryPointPerkEntry 74 | { 75 | return (EntryPointFunction)(*(System.Byte*)entryPointPerkEntry.AddByteOffset(0x11)); 76 | } 77 | 78 | static public System.Byte ArgumentCount(this ref TBGSEntryPointPerkEntry entryPointPerkEntry) 79 | where TBGSEntryPointPerkEntry : unmanaged, Eggstensions.IBGSEntryPointPerkEntry 80 | { 81 | return *(System.Byte*)entryPointPerkEntry.AddByteOffset(0x12); 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/B/BGSMovementType.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IBGSMovementType : ITESForm 4 | { 5 | } 6 | 7 | public struct BGSMovementType : IBGSMovementType 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/B/BGSPerkEntry.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public enum EntryPoint : System.Byte 4 | { 5 | ModSpellMagnitude = 29, 6 | ModArmorWeight = 32, 7 | ApplyCombatHitSpell = 51, 8 | ApplyBashingSpell = 52, 9 | ApplyReanimateSpell = 53, 10 | ApplyWeaponSwingSpell = 67, 11 | ApplySneakingSpell = 69 12 | } 13 | 14 | public enum EntryPointFunction : System.Byte 15 | { 16 | SelectSpell = 10 17 | } 18 | 19 | public enum EntryPointFunctionResult : System.Byte 20 | { 21 | Value = 0, 22 | LeveledList = 1, 23 | ActivateChoice = 2, 24 | // 3 25 | SpellItem = 4, 26 | BooleanGraphVariable = 5, 27 | Text = 6 28 | } 29 | 30 | public enum PerkEntryType : System.Byte 31 | { 32 | Quest = 0, 33 | Ability = 1, 34 | EntryPoint = 2 35 | } 36 | 37 | 38 | 39 | public interface IBGSPerkEntry : IVirtualObject 40 | { 41 | } 42 | 43 | public struct BGSPerkEntry : IBGSPerkEntry 44 | { 45 | } 46 | 47 | 48 | 49 | namespace ExtensionMethods 50 | { 51 | unsafe static public class IBGSPerkEntry 52 | { 53 | // Field 54 | static public System.Byte Rank(this ref TBGSPerkEntry perkEntry) 55 | where TBGSPerkEntry : unmanaged, Eggstensions.IBGSPerkEntry 56 | { 57 | return *(System.Byte*)perkEntry.AddByteOffset(0x8); 58 | } 59 | 60 | static public System.Byte Priority(this ref TBGSPerkEntry perkEntry) 61 | where TBGSPerkEntry : unmanaged, Eggstensions.IBGSPerkEntry 62 | { 63 | return *(System.Byte*)perkEntry.AddByteOffset(0x9); 64 | } 65 | 66 | 67 | 68 | // Virtual 69 | static public System.Boolean EvaluateConditions(this ref TBGSPerkEntry perkEntry, System.Int32 argumentCount, System.IntPtr arguments) 70 | where TBGSPerkEntry : unmanaged, Eggstensions.IBGSPerkEntry 71 | { 72 | var evaluateConditions = (delegate* unmanaged[Cdecl])perkEntry.VirtualFunction(0x0); 73 | 74 | return EvaluateConditions(perkEntry.AsPointer(), argumentCount, arguments) != 0; 75 | 76 | 77 | 78 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 79 | System.Byte EvaluateConditions(TBGSPerkEntry* perkEntry, System.Int32 argumentCount, System.IntPtr arguments) 80 | { 81 | return evaluateConditions(perkEntry, argumentCount, arguments); 82 | } 83 | } 84 | 85 | static public EntryPointFunction GetFunction(this ref TBGSPerkEntry perkEntry) 86 | where TBGSPerkEntry : unmanaged, Eggstensions.IBGSPerkEntry 87 | { 88 | var getFunction = (delegate* unmanaged[Cdecl])perkEntry.VirtualFunction(0x1); 89 | 90 | return (EntryPointFunction)GetFunction(perkEntry.AsPointer()); 91 | 92 | 93 | 94 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 95 | System.Byte GetFunction(TBGSPerkEntry* perkEntry) 96 | { 97 | return getFunction(perkEntry); 98 | } 99 | } 100 | 101 | static public BGSEntryPointFunctionData* GetFunctionData(this ref TBGSPerkEntry perkEntry) 102 | where TBGSPerkEntry : unmanaged, Eggstensions.IBGSPerkEntry 103 | { 104 | var getFunctionData = (delegate* unmanaged[Cdecl])perkEntry.VirtualFunction(0x2); 105 | 106 | return GetFunctionData(perkEntry.AsPointer()); 107 | 108 | 109 | 110 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 111 | BGSEntryPointFunctionData* GetFunctionData(TBGSPerkEntry* perkEntry) 112 | { 113 | return getFunctionData(perkEntry); 114 | } 115 | } 116 | 117 | static public void AddPerkEntry(this ref TBGSPerkEntry perkEntry, TActor* perkOwner) 118 | where TBGSPerkEntry : unmanaged, Eggstensions.IBGSPerkEntry 119 | where TActor : unmanaged, Eggstensions.IActor 120 | { 121 | var addPerkEntry = (delegate* unmanaged[Cdecl])perkEntry.VirtualFunction(0xA); 122 | 123 | AddPerkEntry(perkEntry.AsPointer(), perkOwner); 124 | 125 | 126 | 127 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 128 | void AddPerkEntry(TBGSPerkEntry* perkEntry, TActor* perkOwner) 129 | { 130 | addPerkEntry(perkEntry, perkOwner); 131 | } 132 | } 133 | 134 | static public void RemovePerkEntry(this ref TBGSPerkEntry perkEntry, TActor* perkOwner) 135 | where TBGSPerkEntry : unmanaged, Eggstensions.IBGSPerkEntry 136 | where TActor : unmanaged, Eggstensions.IActor 137 | { 138 | var removePerkEntry = (delegate* unmanaged[Cdecl])perkEntry.VirtualFunction(0xB); 139 | 140 | RemovePerkEntry(perkEntry.AsPointer(), perkOwner); 141 | 142 | 143 | 144 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 145 | void RemovePerkEntry(TBGSPerkEntry* perkEntry, TActor* perkOwner) 146 | { 147 | removePerkEntry(perkEntry, perkOwner); 148 | } 149 | } 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/B/BSAttachTechniques.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | namespace BSAttachTechniques 4 | { 5 | public interface IAttachTechniqueInput : IVirtualObject 6 | { 7 | } 8 | 9 | public struct AttachTechniqueInput : IAttachTechniqueInput 10 | { 11 | } 12 | } 13 | 14 | 15 | 16 | namespace ExtensionMethods 17 | { 18 | namespace BSAttachTechniques 19 | { 20 | unsafe static public class IAttachTechniqueInput 21 | { 22 | // Field 23 | static public NiNode* AttachRoot(this ref TAttachTechniqueInput attachTechniqueInput) 24 | where TAttachTechniqueInput : unmanaged, Eggstensions.BSAttachTechniques.IAttachTechniqueInput 25 | { 26 | return *(NiNode**)attachTechniqueInput.AddByteOffset(0x8); 27 | } 28 | 29 | static public NiNode* EffectRoot(this ref TAttachTechniqueInput attachTechniqueInput) 30 | where TAttachTechniqueInput : unmanaged, Eggstensions.BSAttachTechniques.IAttachTechniqueInput 31 | { 32 | return *(NiNode**)attachTechniqueInput.AddByteOffset(0x10); 33 | } 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/B/BSFixedString.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions.ExtensionMethods; 2 | 3 | 4 | 5 | namespace Eggstensions 6 | { 7 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x8)] 8 | unsafe public struct BSFixedString : System.IDisposable 9 | { 10 | public BSFixedString(System.String text) : this() 11 | { 12 | BSFixedString.Initialize(this.AsPointer(), text); 13 | } 14 | 15 | 16 | 17 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.IntPtr Text; 18 | 19 | 20 | 21 | // Member 22 | public void Dispose() 23 | { 24 | BSFixedString.Release(this.AsPointer()); 25 | } 26 | 27 | 28 | 29 | // Static 30 | static public BSFixedString* Initialize(BSFixedString* fixedString, System.String text) 31 | { 32 | var initialize = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.BSFixedString.Initialize; 33 | 34 | return Initialize(fixedString, new UnmanagedType.LPStr { Value = text }); 35 | 36 | 37 | 38 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 39 | BSFixedString* Initialize(BSFixedString* fixedString, UnmanagedType.LPStr text) 40 | { 41 | return initialize(fixedString, text); 42 | } 43 | } 44 | 45 | static public void Release(BSFixedString* fixedString) 46 | { 47 | var release = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.BSFixedString.Release; 48 | 49 | Release(fixedString); 50 | 51 | 52 | 53 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 54 | void Release(BSFixedString* fixedString) 55 | { 56 | release(fixedString); 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/B/BSHandleRefObject.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IBSHandleRefObject : INiRefObject 4 | { 5 | } 6 | 7 | public struct BSHandleRefObject : IBSHandleRefObject 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class IBSHandleRefObject 16 | { 17 | // Member 18 | static public void DecrementReferenceCount(this ref TBSHandleRefObject handleReferenceObject) 19 | where TBSHandleRefObject : unmanaged, Eggstensions.IBSHandleRefObject 20 | { 21 | if (System.Threading.Interlocked.Decrement(ref *handleReferenceObject.ReferenceCount()) == 0) 22 | { 23 | handleReferenceObject.Delete(); 24 | } 25 | } 26 | 27 | static public void IncrementReferenceCount(this ref TBSHandleRefObject handleReferenceObject) 28 | where TBSHandleRefObject : unmanaged, Eggstensions.IBSHandleRefObject 29 | { 30 | System.Threading.Interlocked.Increment(ref *handleReferenceObject.ReferenceCount()); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/B/BSPointerHandle.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x4)] 4 | unsafe public struct BSPointerHandle 5 | { 6 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.UInt32 Handle; 7 | 8 | 9 | 10 | // Static 11 | static public BSPointerHandle* GetHandle(BSPointerHandle* handle, NiPointer smartPointer) 12 | { 13 | var getHandle = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.BSPointerHandle.GetHandle; 14 | 15 | return GetHandle(handle, smartPointer); 16 | 17 | 18 | 19 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 20 | BSPointerHandle* GetHandle(BSPointerHandle* handle, NiPointer smartPointer) 21 | { 22 | return getHandle(handle, smartPointer); 23 | } 24 | } 25 | 26 | static public System.Boolean GetSmartPointer(BSPointerHandle* handle, NiPointer* smartPointer) 27 | { 28 | var getSmartPointer = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.BSPointerHandle.GetSmartPointer; 29 | 30 | return GetSmartPointer(handle, smartPointer) != 0; 31 | 32 | 33 | 34 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 35 | System.Byte GetSmartPointer(BSPointerHandle* handle, NiPointer* smartPointer) 36 | { 37 | return getSmartPointer(handle, smartPointer); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/B/BSTArray.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions.ExtensionMethods; 2 | 3 | 4 | 5 | namespace Eggstensions 6 | { 7 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x18)] 8 | unsafe public struct BSTArray : System.IDisposable 9 | { 10 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.IntPtr Elements; 11 | [System.Runtime.InteropServices.FieldOffset(0x8)] public System.Int32 Capacity; 12 | [System.Runtime.InteropServices.FieldOffset(0x10)] public System.Int32 Length; 13 | 14 | 15 | 16 | // Member 17 | public void Deallocate() 18 | { 19 | var deallocate = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.BSTArray.Deallocate; 20 | 21 | Deallocate(this.AsPointer()); 22 | 23 | 24 | 25 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 26 | void Deallocate(BSTArray* array) 27 | { 28 | deallocate(array); 29 | } 30 | } 31 | 32 | public void Dispose() 33 | { 34 | Deallocate(); 35 | } 36 | 37 | public System.Int32 Push(void* element) 38 | { 39 | var push = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.BSTArray.IntPtr.Push; 40 | 41 | return Push(this.AsPointer(), element); 42 | 43 | 44 | 45 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 46 | System.Int32 Push(BSTArray* array, void* element) 47 | { 48 | return push(array, element); 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/B/BSTEventSink.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public enum BSEventNotifyControl : System.Int32 4 | { 5 | Continue = 0, 6 | Stop = 1 7 | } 8 | 9 | 10 | 11 | unsafe public class BSTEventSink : System.IDisposable 12 | { 13 | /// BSEventNotifyControl ProcessEvent(System.IntPtr eventSink, void* eventArguments, void* eventSource) 14 | public BSTEventSink(delegate* unmanaged[Cdecl] processEvent) 15 | { 16 | VirtualFunctionTable = System.Runtime.InteropServices.Marshal.AllocHGlobal(0x2 * System.Runtime.CompilerServices.Unsafe.SizeOf()); 17 | Address = System.Runtime.InteropServices.Marshal.AllocHGlobal(0x1 * System.Runtime.CompilerServices.Unsafe.SizeOf()); 18 | 19 | ((System.IntPtr*)VirtualFunctionTable)[0] = new System.IntPtr((delegate* unmanaged[Cdecl])&Destructor); 20 | ((System.IntPtr*)VirtualFunctionTable)[1] = new System.IntPtr(processEvent); 21 | *(System.IntPtr*)Address = VirtualFunctionTable; 22 | 23 | 24 | 25 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 26 | static void Destructor(System.IntPtr eventSink) 27 | { 28 | System.Runtime.InteropServices.Marshal.FreeHGlobal(eventSink); // Address 29 | System.Runtime.InteropServices.Marshal.FreeHGlobal(*(System.IntPtr*)eventSink); // VirtualFunctionTable 30 | } 31 | } 32 | 33 | 34 | 35 | public System.IntPtr Address { get; } 36 | public System.IntPtr VirtualFunctionTable { get; } 37 | 38 | 39 | 40 | public void Dispose() 41 | { 42 | System.Runtime.InteropServices.Marshal.FreeHGlobal(Address); 43 | System.Runtime.InteropServices.Marshal.FreeHGlobal(VirtualFunctionTable); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/B/BSTEventSource.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions.ExtensionMethods; 2 | 3 | 4 | 5 | namespace Eggstensions 6 | { 7 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x58)] 8 | unsafe public struct BSTEventSource 9 | { 10 | // Member 11 | public void AddEventSink(System.IntPtr eventSink) 12 | { 13 | var addEventSink = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.BSTEventSource.AddEventSink; 14 | 15 | AddEventSink(this.AsPointer(), eventSink); 16 | 17 | 18 | 19 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 20 | void AddEventSink(BSTEventSource* eventSource, System.IntPtr eventSink) 21 | { 22 | addEventSink(eventSource, eventSink); 23 | } 24 | } 25 | 26 | public void RemoveEventSink(System.IntPtr eventSink) 27 | { 28 | var removeEventSink = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.BSTEventSource.RemoveEventSink; 29 | 30 | RemoveEventSink(this.AsPointer(), eventSink); 31 | 32 | 33 | 34 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 35 | void RemoveEventSink(BSTEventSource* eventSource, System.IntPtr eventSink) 36 | { 37 | removeEventSink(eventSource, eventSink); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/B/bhkWorld.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IbhkWorld : IVirtualObject 4 | { 5 | } 6 | 7 | public struct bhkWorld : IbhkWorld 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/C/Color.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x4)] 4 | public struct Color 5 | { 6 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.Byte Red; 7 | [System.Runtime.InteropServices.FieldOffset(0x1)] public System.Byte Green; 8 | [System.Runtime.InteropServices.FieldOffset(0x2)] public System.Byte Blue; 9 | [System.Runtime.InteropServices.FieldOffset(0x3)] public System.Byte Alpha; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/Context.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x190)] 4 | public struct Context 5 | { 6 | [System.Runtime.InteropServices.FieldOffset(0x0)] public FloatingPointRegister Xmm0; 7 | [System.Runtime.InteropServices.FieldOffset(0x10)] public FloatingPointRegister Xmm1; 8 | [System.Runtime.InteropServices.FieldOffset(0x20)] public FloatingPointRegister Xmm2; 9 | [System.Runtime.InteropServices.FieldOffset(0x30)] public FloatingPointRegister Xmm3; 10 | [System.Runtime.InteropServices.FieldOffset(0x40)] public FloatingPointRegister Xmm4; 11 | [System.Runtime.InteropServices.FieldOffset(0x50)] public FloatingPointRegister Xmm5; 12 | [System.Runtime.InteropServices.FieldOffset(0x60)] public FloatingPointRegister Xmm6; 13 | [System.Runtime.InteropServices.FieldOffset(0x70)] public FloatingPointRegister Xmm7; 14 | [System.Runtime.InteropServices.FieldOffset(0x80)] public FloatingPointRegister Xmm8; 15 | [System.Runtime.InteropServices.FieldOffset(0x90)] public FloatingPointRegister Xmm9; 16 | [System.Runtime.InteropServices.FieldOffset(0xA0)] public FloatingPointRegister Xmm10; 17 | [System.Runtime.InteropServices.FieldOffset(0xB0)] public FloatingPointRegister Xmm11; 18 | [System.Runtime.InteropServices.FieldOffset(0xC0)] public FloatingPointRegister Xmm12; 19 | [System.Runtime.InteropServices.FieldOffset(0xD0)] public FloatingPointRegister Xmm13; 20 | [System.Runtime.InteropServices.FieldOffset(0xE0)] public FloatingPointRegister Xmm14; 21 | [System.Runtime.InteropServices.FieldOffset(0xF0)] public FloatingPointRegister Xmm15; 22 | [System.Runtime.InteropServices.FieldOffset(0x100)] public IntegerRegister Rax; 23 | [System.Runtime.InteropServices.FieldOffset(0x108)] public IntegerRegister Rbx; 24 | [System.Runtime.InteropServices.FieldOffset(0x110)] public IntegerRegister Rcx; 25 | [System.Runtime.InteropServices.FieldOffset(0x118)] public IntegerRegister Rdx; 26 | [System.Runtime.InteropServices.FieldOffset(0x120)] public IntegerRegister Rsi; 27 | [System.Runtime.InteropServices.FieldOffset(0x128)] public IntegerRegister Rdi; 28 | [System.Runtime.InteropServices.FieldOffset(0x130)] public IntegerRegister R8; 29 | [System.Runtime.InteropServices.FieldOffset(0x138)] public IntegerRegister R9; 30 | [System.Runtime.InteropServices.FieldOffset(0x140)] public IntegerRegister R12; 31 | [System.Runtime.InteropServices.FieldOffset(0x148)] public IntegerRegister R13; 32 | [System.Runtime.InteropServices.FieldOffset(0x150)] public IntegerRegister R14; 33 | [System.Runtime.InteropServices.FieldOffset(0x158)] public IntegerRegister R15; 34 | [System.Runtime.InteropServices.FieldOffset(0x160)] public IntegerRegister R10; 35 | [System.Runtime.InteropServices.FieldOffset(0x168)] public IntegerRegister Rbp; 36 | [System.Runtime.InteropServices.FieldOffset(0x170)] public FlagsRegister Flags; 37 | [System.Runtime.InteropServices.FieldOffset(0x178)] public IntegerRegister R11; 38 | [System.Runtime.InteropServices.FieldOffset(0x180)] public IntegerRegister Rsp; 39 | [System.Runtime.InteropServices.FieldOffset(0x188)] public IntegerRegister Rip; 40 | } 41 | 42 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x8)] 43 | public struct FlagsRegister 44 | { 45 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.UInt32 UInt32; 46 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.UInt64 UInt64; 47 | } 48 | 49 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x10)] 50 | public struct FloatingPointRegister 51 | { 52 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.Single Single; 53 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.Double Double; 54 | } 55 | 56 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x8)] 57 | public struct IntegerRegister 58 | { 59 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.Byte Byte; 60 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.Double Double; 61 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.Int16 Int16; 62 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.Int32 Int32; 63 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.Int64 Int64; 64 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.IntPtr IntPtr; 65 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.SByte SByte; 66 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.Single Single; 67 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.UInt16 UInt16; 68 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.UInt32 UInt32; 69 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.UInt64 UInt64; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/DNNE.cs: -------------------------------------------------------------------------------- 1 | namespace DNNE 2 | { 3 | internal class C99DeclCodeAttribute : System.Attribute 4 | { 5 | public C99DeclCodeAttribute(System.String code) 6 | { 7 | } 8 | } 9 | 10 | internal class C99TypeAttribute : System.Attribute 11 | { 12 | public C99TypeAttribute(System.String code) 13 | { 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/E/Effect.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x28)] 4 | unsafe public struct Effect 5 | { 6 | [System.Runtime.InteropServices.FieldOffset(0x10)] public EffectSetting* BaseEffect; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/E/EffectSetting.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public enum EffectArchetype : System.Int32 4 | { 5 | AccumulateMagnitude = 32 6 | } 7 | 8 | [System.Flags] 9 | public enum EffectSettingDataFlags : System.UInt32 10 | { 11 | NoDuration = 1U << 9, 12 | NoMagnitude = 1U << 10, 13 | NoArea = 1U << 11, 14 | PowerAffectsMagnitude = 1U << 21, 15 | PowerAffectsDuration = 1U << 22 16 | } 17 | 18 | 19 | 20 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0xF0)] 21 | public struct EffectSettingData 22 | { 23 | [System.Runtime.InteropServices.FieldOffset(0x0)] public EffectSettingDataFlags Flags; 24 | [System.Runtime.InteropServices.FieldOffset(0x10)] public ActorValue MagicSkill; 25 | [System.Runtime.InteropServices.FieldOffset(0x28)] public System.Single TaperWeight; 26 | [System.Runtime.InteropServices.FieldOffset(0x4C)] public System.Single TaperCurve; 27 | [System.Runtime.InteropServices.FieldOffset(0x50)] public System.Single TaperDuration; 28 | [System.Runtime.InteropServices.FieldOffset(0x58)] public EffectArchetype EffectArchetype; 29 | } 30 | 31 | 32 | 33 | public interface IEffectSetting : ITESForm 34 | { 35 | } 36 | 37 | public struct EffectSetting : IEffectSetting 38 | { 39 | } 40 | 41 | 42 | 43 | namespace ExtensionMethods 44 | { 45 | unsafe static public class IEffectSetting 46 | { 47 | // Field 48 | static public EffectSettingData* Data(this ref TEffectSetting effectSetting) 49 | where TEffectSetting : unmanaged, Eggstensions.IEffectSetting 50 | { 51 | return (EffectSettingData*)effectSetting.AddByteOffset(0x68); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/E/EnchantmentItem.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IEnchantmentItem : IMagicItem 4 | { 5 | } 6 | 7 | public struct EnchantmentItem : IEnchantmentItem 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/E/ExtraDataList.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions.ExtensionMethods; 2 | 3 | 4 | 5 | namespace Eggstensions 6 | { 7 | public enum ExtraDataType : System.Int32 8 | { 9 | Charge = 0x28, 10 | Enchantment = 0x9B 11 | } 12 | 13 | 14 | 15 | unsafe public struct ExtraDataList 16 | { 17 | public System.Single GetCharge() 18 | { 19 | var getCharge = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.ExtraDataList.GetCharge; 20 | 21 | return GetCharge(this.AsPointer()); 22 | 23 | 24 | 25 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 26 | System.Single GetCharge(ExtraDataList* extraDataList) 27 | { 28 | return getCharge(extraDataList); 29 | } 30 | } 31 | 32 | public System.Boolean HasExtraData(ExtraDataType extraDataType) 33 | { 34 | var hasExtraData = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.ExtraDataList.HasExtraData; 35 | 36 | return HasExtraData(this.AsPointer(), (System.Int32)extraDataType) != 0; 37 | 38 | 39 | 40 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 41 | System.Byte HasExtraData(ExtraDataList* extraDataList, System.Int32 extraDataType) 42 | { 43 | return hasExtraData(extraDataList, extraDataType); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/Eggstensions.projitems: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | 740eff05-9743-47ce-b6ea-09584eaf1edf 7 | 8 | 9 | Eggstensions 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/Eggstensions.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 740eff05-9743-47ce-b6ea-09584eaf1edf 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/Events.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | namespace Events 4 | { 5 | unsafe static public class InitializeThread 6 | { 7 | static InitializeThread() 8 | { 9 | InitializeThread.initializeThread = (delegate* unmanaged[Cdecl])((System.IntPtr*)Eggstensions.Offsets.InitTESThread.VirtualFunctionTable)[0x1]; 10 | 11 | Memory.WriteVirtualFunction(Eggstensions.Offsets.InitTESThread.VirtualFunctionTable, 0x1, (delegate* unmanaged[Cdecl])&InitializeThread.OnInitializeThread); 12 | } 13 | 14 | 15 | 16 | static private delegate* unmanaged[Cdecl] initializeThread; 17 | 18 | 19 | 20 | static public event System.EventHandler After; 21 | static public event System.EventHandler Before; 22 | 23 | 24 | 25 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 26 | static private void OnInitializeThread(InitTESThread* initializeThread) 27 | { 28 | InitializeThread.Before?.Invoke(null, System.EventArgs.Empty); 29 | InitializeThread.initializeThread(initializeThread); 30 | InitializeThread.After?.Invoke(null, System.EventArgs.Empty); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/ExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | namespace ExtensionMethods 4 | { 5 | unsafe static public class Unsafe 6 | { 7 | static public void* AddByteOffset(this ref T source, System.Int32 byteOffset) 8 | where T : unmanaged 9 | { 10 | return System.Runtime.CompilerServices.Unsafe.Add(source.AsPointer(), byteOffset); 11 | } 12 | 13 | static public T* AsPointer(this ref T value) 14 | where T : unmanaged 15 | { 16 | return (T*)System.Runtime.CompilerServices.Unsafe.AsPointer(ref value); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/F/FindMaxMagnitudeVisitor.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x18)] 4 | unsafe public struct FindMaxMagnitudeVisitor 5 | { 6 | [System.Runtime.InteropServices.FieldOffset(0x8)] public ActiveEffect* FinishedActiveEffect; 7 | [System.Runtime.InteropServices.FieldOffset(0x10)] public System.Single MaximumMagnitude; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/H/HandleEntryPointVisitor.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x30)] 4 | unsafe public struct HandleEntryPointVisitor 5 | { 6 | [System.Runtime.InteropServices.FieldOffset(0x8)] public EntryPointFunctionResult Result; 7 | [System.Runtime.InteropServices.FieldOffset(0x10)] public System.IntPtr Arguments; // ArgumentCount 8 | [System.Runtime.InteropServices.FieldOffset(0x18)] public System.IntPtr Results; // ResultCount 9 | [System.Runtime.InteropServices.FieldOffset(0x20)] public Actor* PerkOwner; 10 | [System.Runtime.InteropServices.FieldOffset(0x28)] public System.Byte ArgumentCount; 11 | [System.Runtime.InteropServices.FieldOffset(0x29)] public System.Byte ResultCount; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/I/IAnimationGraphManagerHolder.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IIAnimationGraphManagerHolder : IVirtualObject 4 | { 5 | } 6 | 7 | public struct IAnimationGraphManagerHolder : IIAnimationGraphManagerHolder 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class IIAnimationGraphManagerHolder 16 | { 17 | // Virtual 18 | static public System.Boolean GetAnimationVariableFloat(this ref TIAnimationGraphManagerHolder animationGraphManagerHolder, BSFixedString* variableName, System.Single* value) 19 | where TIAnimationGraphManagerHolder : unmanaged, Eggstensions.IIAnimationGraphManagerHolder 20 | { 21 | var getAnimationVariableFloat = (delegate* unmanaged[Cdecl])animationGraphManagerHolder.VirtualFunction(0x10); 22 | 23 | return GetAnimationVariableFloat(animationGraphManagerHolder.AsPointer(), variableName, value) != 0; 24 | 25 | 26 | 27 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 28 | System.Byte GetAnimationVariableFloat(TIAnimationGraphManagerHolder* animationGraphManagerHolder, BSFixedString* variableName, System.Single* value) 29 | { 30 | return getAnimationVariableFloat(animationGraphManagerHolder, variableName, value); 31 | } 32 | } 33 | 34 | static public System.Boolean GetAnimationVariableInt(this ref TIAnimationGraphManagerHolder animationGraphManagerHolder, BSFixedString* variableName, System.Int32* value) 35 | where TIAnimationGraphManagerHolder : unmanaged, Eggstensions.IIAnimationGraphManagerHolder 36 | { 37 | var getAnimationVariableInt = (delegate* unmanaged[Cdecl])animationGraphManagerHolder.VirtualFunction(0x11); 38 | 39 | return GetAnimationVariableInt(animationGraphManagerHolder.AsPointer(), variableName, value) != 0; 40 | 41 | 42 | 43 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 44 | System.Byte GetAnimationVariableInt(TIAnimationGraphManagerHolder* animationGraphManagerHolder, BSFixedString* variableName, System.Int32* value) 45 | { 46 | return getAnimationVariableInt(animationGraphManagerHolder, variableName, value); 47 | } 48 | } 49 | 50 | static public System.Boolean GetAnimationVariableBool(this ref TIAnimationGraphManagerHolder animationGraphManagerHolder, BSFixedString* variableName, System.Byte* value) 51 | where TIAnimationGraphManagerHolder : unmanaged, Eggstensions.IIAnimationGraphManagerHolder 52 | { 53 | var getAnimationVariableBool = (delegate* unmanaged[Cdecl])animationGraphManagerHolder.VirtualFunction(0x12); 54 | 55 | return GetAnimationVariableBool(animationGraphManagerHolder.AsPointer(), variableName, value) != 0; 56 | 57 | 58 | 59 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 60 | System.Byte GetAnimationVariableBool(TIAnimationGraphManagerHolder* animationGraphManagerHolder, BSFixedString* variableName, System.Byte* value) 61 | { 62 | return getAnimationVariableBool(animationGraphManagerHolder, variableName, value); 63 | } 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/I/InitTESThread.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IInitTESThread : IVirtualObject 4 | { 5 | } 6 | 7 | public struct InitTESThread : IInitTESThread 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/I/InventoryChanges.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions.ExtensionMethods; 2 | 3 | 4 | 5 | namespace Eggstensions 6 | { 7 | unsafe public struct InventoryChanges 8 | { 9 | public void ResetWeight() 10 | { 11 | var resetWeight = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.InventoryChanges.ResetWeight; 12 | 13 | ResetWeight(this.AsPointer()); 14 | 15 | 16 | 17 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 18 | void ResetWeight(InventoryChanges* inventoryChanges) 19 | { 20 | resetWeight(inventoryChanges); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/I/InventoryEntryData.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions.ExtensionMethods; 2 | 3 | 4 | 5 | namespace Eggstensions 6 | { 7 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x18)] 8 | unsafe public struct InventoryEntryData 9 | { 10 | [System.Runtime.InteropServices.FieldOffset(0x0)] public TESBoundObject* Item; 11 | 12 | 13 | 14 | // Member 15 | public System.Boolean IsWorn() 16 | { 17 | var isWorn = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.InventoryEntryData.IsWorn; 18 | 19 | return IsWorn(this.AsPointer()) != 0; 20 | 21 | 22 | 23 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 24 | System.Byte IsWorn(InventoryEntryData* inventoryEntryData) 25 | { 26 | return isWorn(inventoryEntryData); 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/Log.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public class Log 4 | { 5 | readonly static private System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(System.IO.Path.Combine(Main.ExecutingAssemblyDirectoryName, $"{Main.ExecutingAssemblyName}.log"), false) { AutoFlush = true }; 6 | 7 | 8 | 9 | static public void Error(System.String value, [System.Runtime.CompilerServices.CallerFilePath] System.String filePath = "", [System.Runtime.CompilerServices.CallerLineNumber] System.Int32 lineNumber = 0) 10 | { 11 | streamWriter.WriteLine($"[{System.DateTime.Now}] {filePath}:line {lineNumber}: {value}"); 12 | } 13 | 14 | static public void Information(System.String value) 15 | { 16 | streamWriter.WriteLine($"[{System.DateTime.Now}] {value}"); 17 | } 18 | 19 | // Warning 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/M/MagicCaster.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IMagicCaster : IVirtualObject 4 | { 5 | } 6 | 7 | public struct MagicCaster : IMagicCaster 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class IMagicCaster 16 | { 17 | // Virtual 18 | /// SkyrimSE.exe + 0x54C5F0 (VID 33626) 19 | /// SkyrimSE.exe + 0x551980 (VID 33683) 20 | /// SkyrimSE.exe + 0x540360 (VID 33320) 21 | /// SkyrimSE.exe + 0x53DEB0 (VID 33277) 22 | /// SkyrimSE.exe + 0x54C5F0 (VID 33626) 23 | static public void Cast(this ref TMagicCaster magicCaster, TSpellItem* spell, System.Boolean noHitEffectArt, TActor1* target, System.Single effectiveness, System.Boolean hostileEffectivenessOnly, System.Single magnitudeOverride, TActor2* cause) 24 | where TMagicCaster : unmanaged, Eggstensions.IMagicCaster 25 | where TSpellItem : unmanaged, Eggstensions.ISpellItem 26 | where TActor1 : unmanaged, Eggstensions.IActor 27 | where TActor2 : unmanaged, Eggstensions.IActor 28 | { 29 | var cast = (delegate* unmanaged[Cdecl])magicCaster.VirtualFunction(0x1); 30 | 31 | Cast(magicCaster.AsPointer(), spell, (System.Byte)(noHitEffectArt ? 1 : 0), target, effectiveness, (System.Byte)(hostileEffectivenessOnly ? 1 : 0), magnitudeOverride, cause); 32 | 33 | 34 | 35 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 36 | void Cast(TMagicCaster* magicCaster, TSpellItem* spell, System.Byte noHitEffectArt, TActor1* target, System.Single effectiveness, System.Byte hostileEffectivenessOnly, System.Single magnitudeOverride, TActor2* cause) 37 | { 38 | cast(magicCaster, spell, noHitEffectArt, target, effectiveness, hostileEffectivenessOnly, magnitudeOverride, cause); 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/M/MagicItem.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public enum CastingSource : System.Int32 4 | { 5 | LeftHand = 0, 6 | RightHand = 1, 7 | Other = 2, 8 | Instant = 3 9 | } 10 | 11 | public enum CastingType : System.Int32 12 | { 13 | ConstantEffect = 0, 14 | FireAndForget = 1, 15 | Concentration = 2, 16 | Scroll = 3 17 | } 18 | 19 | public enum SpellType : System.Int32 20 | { 21 | Spell = 0, 22 | Disease = 1, 23 | Power = 2, 24 | LesserPower = 3, 25 | Ability = 4, 26 | Poison = 5, 27 | Enchantment = 6, 28 | Potion = 7, 29 | Ingredient = 8, 30 | LeveledSpell = 9, 31 | Addiction = 10, 32 | VoicePower = 11, 33 | StaffEnchantment = 12, 34 | Scroll = 13, 35 | 36 | AddSpell = (1 << Disease) | (1 << Ability) | (1 << Addiction) 37 | } 38 | 39 | 40 | 41 | public interface IMagicItem : ITESBoundObject 42 | { 43 | } 44 | 45 | public struct MagicItem : IMagicItem 46 | { 47 | } 48 | 49 | 50 | 51 | namespace ExtensionMethods 52 | { 53 | unsafe static public class IMagicItem 54 | { 55 | // Inheritance 56 | static public TESFullName* TESFullName(this ref TMagicItem magicItem) 57 | where TMagicItem : unmanaged, Eggstensions.IMagicItem 58 | { 59 | return (TESFullName*)magicItem.AddByteOffset(0x30); 60 | } 61 | 62 | 63 | 64 | // Virtual 65 | static public SpellType GetSpellType(this ref TMagicItem magicItem) 66 | where TMagicItem : unmanaged, Eggstensions.IMagicItem 67 | { 68 | var getSpellType = (delegate* unmanaged[Cdecl])magicItem.VirtualFunction(0x53); 69 | 70 | return (SpellType)GetSpellType(magicItem.AsPointer()); 71 | 72 | 73 | 74 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 75 | System.Int32 GetSpellType(TMagicItem* magicItem) 76 | { 77 | return getSpellType(magicItem); 78 | } 79 | } 80 | 81 | static public CastingType GetCastingType(this ref TMagicItem magicItem) 82 | where TMagicItem : unmanaged, Eggstensions.IMagicItem 83 | { 84 | var getCastingType = (delegate* unmanaged[Cdecl])magicItem.VirtualFunction(0x55); 85 | 86 | return (CastingType)GetCastingType(magicItem.AsPointer()); 87 | 88 | 89 | 90 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 91 | System.Int32 GetCastingType(TMagicItem* magicItem) 92 | { 93 | return getCastingType(magicItem); 94 | } 95 | } 96 | 97 | 98 | 99 | // Member 100 | static public System.Single GetCost(this ref TMagicItem magicItem, TActor* caster) 101 | where TMagicItem : unmanaged, Eggstensions.IMagicItem 102 | where TActor : unmanaged, Eggstensions.IActor 103 | { 104 | var getCost = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.MagicItem.GetCost; 105 | 106 | return GetCost(magicItem.AsPointer(), caster); 107 | 108 | 109 | 110 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 111 | System.Single GetCost(TMagicItem* magicItem, TActor* caster) 112 | { 113 | return getCost(magicItem, caster); 114 | } 115 | } 116 | 117 | static public ActorValue GetCostActorValue(this ref TMagicItem magicItem, System.Boolean rightHand) 118 | where TMagicItem : unmanaged, Eggstensions.IMagicItem 119 | { 120 | var getCostActorValue = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.MagicItem.GetCostActorValue; 121 | 122 | return (ActorValue)GetCostActorValue(magicItem.AsPointer(), rightHand ? 1 : 0); 123 | 124 | 125 | 126 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 127 | System.Int32 GetCostActorValue(TMagicItem* magicItem, System.Int32 rightHand) 128 | { 129 | return getCostActorValue(magicItem, rightHand); 130 | } 131 | } 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/M/MagicTarget.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IMagicTarget : IVirtualObject 4 | { 5 | } 6 | 7 | public struct MagicTarget : IMagicTarget 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class IMagicTarget 16 | { 17 | // Member 18 | static public Actor* GetActor(this ref TMagicTarget magicTarget) 19 | where TMagicTarget : unmanaged, Eggstensions.IMagicTarget 20 | { 21 | var getActor = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.MagicTarget.GetActor; 22 | 23 | return GetActor(magicTarget.AsPointer()); 24 | 25 | 26 | 27 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 28 | Actor* GetActor(TMagicTarget* magicTarget) 29 | { 30 | return getActor(magicTarget); 31 | } 32 | } 33 | 34 | static public void VisitActiveEffects(this ref TMagicTarget magicTarget, void* visitor) 35 | where TMagicTarget : unmanaged, Eggstensions.IMagicTarget 36 | { 37 | var visitActiveEffects = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.MagicTarget.VisitActiveEffects; 38 | 39 | VisitActiveEffects(magicTarget.AsPointer(), visitor); 40 | 41 | 42 | 43 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 44 | void VisitActiveEffects(TMagicTarget* magicTarget, void* visitor) 45 | { 46 | visitActiveEffects(magicTarget, visitor); 47 | } 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/M/MissileProjectile.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IMissileProjectile : IProjectile 4 | { 5 | } 6 | 7 | public struct MissileProjectile : IMissileProjectile 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/M/ModelReferenceEffect.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IModelReferenceEffect : IReferenceEffect 4 | { 5 | } 6 | 7 | public struct ModelReferenceEffect : IModelReferenceEffect 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class IModelReferenceEffect 16 | { 17 | // Field 18 | static public RefAttachTechniqueInput* HitEffectArtData(this ref TModelReferenceEffect modelReferenceEffect) 19 | where TModelReferenceEffect : unmanaged, Eggstensions.IModelReferenceEffect 20 | { 21 | return (RefAttachTechniqueInput*)modelReferenceEffect.AddByteOffset(0x68); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/Main.cs: -------------------------------------------------------------------------------- 1 | [module: System.Runtime.CompilerServices.SkipLocalsInit] 2 | 3 | /* 4 | C# 9.0 function pointers offer better performance and simpler implementation compared to the functions available in the System.Runtime.InteropServices.Marshal class. 5 | However, there are situations where they can cause crashes, which need to be accounted for. Namely, they are: 6 | 1. The JIT Compiler can optimise a function to send a non-blittable type instead of a blittable type as an argument. For example, a System.Boolean instead of a System.Byte. 7 | 2. If function pointer fields or properties are called and are otherwise only initialized inline using for example the Memory.ReadRelativeCall function. 8 | These crashes are prevented in the following ways: 9 | 1. Only call function pointers in functions with blittable type arguments and the [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] attribute. 10 | 2. Always initialize function pointer fields and properties in functions. 11 | */ 12 | 13 | 14 | 15 | namespace Eggstensions 16 | { 17 | public class Main 18 | { 19 | static Main() 20 | { 21 | Main.ExecutingAssembly = System.Reflection.Assembly.GetExecutingAssembly(); 22 | Main.ExecutingAssemblyName = Main.ExecutingAssembly.GetName().Name; 23 | Main.ExecutingAssemblyDirectoryName = System.IO.Path.GetDirectoryName(Main.ExecutingAssembly.Location); 24 | 25 | Main.MainModule = System.Diagnostics.Process.GetCurrentProcess().MainModule; 26 | Main.MainModuleName = Main.MainModule.ModuleName; 27 | Main.MainModuleDirectoryName = System.IO.Path.GetDirectoryName(Main.MainModule.FileName); 28 | 29 | Main.ProductVersion = Main.MainModule.FileVersionInfo.ProductVersion; 30 | Main.ProductVersionMajor = System.Int32.Parse(Main.ProductVersion.Split('.')[0]); 31 | Main.ProductVersionMinor = System.Int32.Parse(Main.ProductVersion.Split('.')[1]); 32 | Main.ProductVersionBuild = System.Int32.Parse(Main.ProductVersion.Split('.')[2]); 33 | Main.ProductVersionPrivate = System.Int32.Parse(Main.ProductVersion.Split('.')[3]); 34 | } 35 | 36 | 37 | 38 | static public System.Diagnostics.ProcessModule MainModule { get; } 39 | static public System.Int32 ProductVersionMajor { get; } 40 | static public System.Int32 ProductVersionMinor { get; } 41 | static public System.Int32 ProductVersionBuild { get; } 42 | static public System.Int32 ProductVersionPrivate { get; } 43 | static public System.Reflection.Assembly ExecutingAssembly { get; } 44 | static public System.String ExecutingAssemblyDirectoryName { get; } 45 | static public System.String ExecutingAssemblyName { get; } 46 | static public System.String MainModuleDirectoryName { get; } 47 | static public System.String MainModuleName { get; } 48 | static public System.String ProductVersion { get; } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/Math.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | static public class Math 4 | { 5 | static public System.IntPtr Ceiling(System.IntPtr value, System.UInt32 multiple) 6 | { 7 | if (multiple == 0) 8 | { 9 | return value; 10 | } 11 | 12 | var remainder = value.ToInt64() % multiple; 13 | 14 | if (remainder == 0) 15 | { 16 | return value; 17 | } 18 | else 19 | { 20 | return new System.IntPtr(value.ToInt64() + multiple - remainder); 21 | } 22 | } 23 | 24 | static public System.IntPtr Floor(System.IntPtr value, System.UInt32 multiple) 25 | { 26 | if (multiple == 0) 27 | { 28 | return value; 29 | } 30 | 31 | var remainder = value.ToInt64() % multiple; 32 | 33 | if (remainder == 0) 34 | { 35 | return value; 36 | } 37 | else 38 | { 39 | return new System.IntPtr(value.ToInt64() - remainder); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/N/NiAVObject.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface INiAVObject : INiObject 4 | { 5 | } 6 | 7 | public struct NiAVObject : INiAVObject 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class INiAVObject 16 | { 17 | // Field 18 | static public NiNode* Parent(this ref TNiAVObject avObject) 19 | where TNiAVObject : unmanaged, Eggstensions.INiAVObject 20 | { 21 | return *(NiNode**)avObject.AddByteOffset(0x30); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/N/NiNode.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface INiNode : INiAVObject 4 | { 5 | } 6 | 7 | public struct NiNode : INiNode 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/N/NiObject.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface INiObject : IVirtualObject 4 | { 5 | } 6 | 7 | public struct NiObject : INiObject 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class INiObject 16 | { 17 | // Virtual 18 | static public NiNode* AsNode(this ref TNiObject niObject) 19 | where TNiObject : unmanaged, Eggstensions.INiObject 20 | { 21 | var asNode = (delegate* unmanaged[Cdecl])niObject.VirtualFunction(0x3); 22 | 23 | return AsNode(niObject.AsPointer()); 24 | 25 | 26 | 27 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 28 | NiNode* AsNode(TNiObject* niObject) 29 | { 30 | return asNode(niObject); 31 | } 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/N/NiPoint3.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0xC)] 4 | public struct NiPoint3 5 | { 6 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.Single X; 7 | [System.Runtime.InteropServices.FieldOffset(0x4)] public System.Single Y; 8 | [System.Runtime.InteropServices.FieldOffset(0x8)] public System.Single Z; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/N/NiPointer.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions.ExtensionMethods; 2 | 3 | 4 | 5 | namespace Eggstensions 6 | { 7 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x8)] 8 | unsafe public struct NiPointer : System.IDisposable 9 | { 10 | public NiPointer(TESObjectREFR* reference) : this() 11 | { 12 | Reference = reference; 13 | Attach(); 14 | } 15 | 16 | 17 | 18 | [System.Runtime.InteropServices.FieldOffset(0x0)] public TESObjectREFR* Reference; 19 | 20 | 21 | 22 | // Member 23 | public void Attach() 24 | { 25 | if (Reference != null) 26 | { 27 | Reference->BSHandleRefObject()->IncrementReferenceCount(); 28 | } 29 | } 30 | 31 | public void Dispose() 32 | { 33 | Detach(); 34 | } 35 | 36 | public void Detach() 37 | { 38 | if (Reference != null) 39 | { 40 | Reference->BSHandleRefObject()->DecrementReferenceCount(); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/N/NiRefObject.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface INiRefObject : IVirtualObject 4 | { 5 | } 6 | 7 | public struct NiRefObject : INiRefObject 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class INiRefObject 16 | { 17 | // Field 18 | static public System.UInt32* ReferenceCount(this ref TNiRefObject referenceObject) 19 | where TNiRefObject : unmanaged, Eggstensions.INiRefObject 20 | { 21 | return (System.UInt32*)referenceObject.AddByteOffset(0x8); 22 | } 23 | 24 | 25 | 26 | // Virtual 27 | static public void Delete(this ref TNiRefObject referenceObject) 28 | where TNiRefObject : unmanaged, Eggstensions.INiRefObject 29 | { 30 | var delete = (delegate* unmanaged[Cdecl])referenceObject.VirtualFunction(0x1); 31 | 32 | Delete(referenceObject.AsPointer()); 33 | 34 | 35 | 36 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 37 | void Delete(TNiRefObject* referenceObject) 38 | { 39 | delete(referenceObject); 40 | } 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/P/PlayerCharacter.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IPlayerCharacter : IActor 4 | { 5 | } 6 | 7 | unsafe public struct PlayerCharacter : IPlayerCharacter 8 | { 9 | static public PlayerCharacter* Instance 10 | { 11 | get 12 | { 13 | return *(PlayerCharacter**)Eggstensions.Offsets.PlayerCharacter.Instance; 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/P/Projectile.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | [System.Flags] 4 | public enum ProjectileFlags : System.UInt32 5 | { 6 | IsHitscan1 = 1U << 0, // SkyrimSE.exe + 0x747910 (VID 42867) + 0x81 7 | IsHitscanHasNoTracers = 1U << 1, // SkyrimSE.exe + 0x747910 (VID 42867) + 0xBF 8 | IsHitscan2 = 1U << 3, // SkyrimSE.exe + 0x747910 (VID 42867) + 0x88 9 | HasTracers = 1U << 4, // SkyrimSE.exe + 0x747910 (VID 42867) + 0x6D 10 | IsHitscanHasTracers = 1U << 5, // SkyrimSE.exe + 0x747910 (VID 42867) + 0xA7 11 | HasGravity = 1U << 6, // SkyrimSE.exe + 0x747910 (VID 42867) + 0xD8 12 | Is3DLoaded = 1U << 8, // SkyrimSE.exe + 0x754820 (VID 43030) + 0xD3 13 | IsArrowQuiver3DHandled = 1U << 26 // SkyrimSE.exe + 0x732390 (VID 42546) + 0x49 14 | } 15 | 16 | 17 | 18 | public interface IProjectile : ITESObjectREFR 19 | { 20 | } 21 | 22 | public struct Projectile : IProjectile 23 | { 24 | } 25 | 26 | 27 | 28 | namespace ExtensionMethods 29 | { 30 | unsafe static public class IProjectile 31 | { 32 | /// SkyrimSE.exe + 0x74A950 (VID 42920) + 0x332 33 | static public System.Single Damage(this ref TProjectile projectile) 34 | where TProjectile : unmanaged, Eggstensions.IProjectile 35 | { 36 | return *(System.Single*)projectile.AddByteOffset(0x198); 37 | } 38 | 39 | static public ProjectileFlags Flags(this ref TProjectile projectile) 40 | where TProjectile : unmanaged, Eggstensions.IProjectile 41 | { 42 | return (ProjectileFlags)(*(System.UInt32*)projectile.AddByteOffset(0x1CC)); 43 | } 44 | 45 | /// SkyrimSE.exe + 0x754DC0 (VID 43035) + 0x1CB 46 | static public System.Byte StartedQueueingFiles(this ref TProjectile projectile) 47 | where TProjectile : unmanaged, Eggstensions.IProjectile 48 | { 49 | return *(System.Byte*)projectile.AddByteOffset(0x1D0); 50 | } 51 | 52 | /// SkyrimSE.exe + 0x754FF0 (VID 43036) + 0x5 53 | static public System.Byte FinishedQueueingFiles(this ref TProjectile projectile) 54 | where TProjectile : unmanaged, Eggstensions.IProjectile 55 | { 56 | return *(System.Byte*)projectile.AddByteOffset(0x1D1); 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/R/RefAttachTechniqueInput.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IRefAttachTechniqueInput : BSAttachTechniques.IAttachTechniqueInput 4 | { 5 | } 6 | 7 | public struct RefAttachTechniqueInput 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class IRefAttachTechniqueInput 16 | { 17 | // Field 18 | static public TESRace* Race(this ref TRefAttachTechniqueInput referenceAttachTechniqueInput) 19 | where TRefAttachTechniqueInput : unmanaged, Eggstensions.IRefAttachTechniqueInput 20 | { 21 | return *(TESRace**)referenceAttachTechniqueInput.AddByteOffset(0x28); 22 | } 23 | 24 | static public bhkWorld* HavokWorld(this ref TRefAttachTechniqueInput referenceAttachTechniqueInput) 25 | where TRefAttachTechniqueInput : unmanaged, Eggstensions.IRefAttachTechniqueInput 26 | { 27 | return *(bhkWorld**)referenceAttachTechniqueInput.AddByteOffset(0x30); 28 | } 29 | 30 | static public BSFixedString* NodeName(this ref TRefAttachTechniqueInput referenceAttachTechniqueInput) 31 | where TRefAttachTechniqueInput : unmanaged, Eggstensions.IRefAttachTechniqueInput 32 | { 33 | return (BSFixedString*)referenceAttachTechniqueInput.AddByteOffset(0x40); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/R/ReferenceEffect.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IReferenceEffect : INiObject 4 | { 5 | } 6 | 7 | public struct ReferenceEffect : IReferenceEffect 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class IReferenceEffect 16 | { 17 | // Field 18 | static public ReferenceEffectController* Controller(this ref TReferenceEffect referenceEffect) 19 | where TReferenceEffect : unmanaged, Eggstensions.IReferenceEffect 20 | { 21 | return *(ReferenceEffectController**)referenceEffect.AddByteOffset(0x30); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/R/ReferenceEffectController.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IReferenceEffectController : IVirtualObject 4 | { 5 | } 6 | 7 | public struct ReferenceEffectController : IReferenceEffectController 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class IReferenceEffectController 16 | { 17 | // Virtual 18 | static public NiAVObject* GetAttachRoot(this ref TReferenceEffectController referenceEffectController) 19 | where TReferenceEffectController : unmanaged, Eggstensions.IReferenceEffectController 20 | { 21 | var getAttachRoot = (delegate* unmanaged[Cdecl])referenceEffectController.VirtualFunction(0xF); 22 | 23 | return GetAttachRoot(referenceEffectController.AsPointer()); 24 | 25 | 26 | 27 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 28 | NiAVObject* GetAttachRoot(TReferenceEffectController* referenceEffectController) 29 | { 30 | return getAttachRoot(referenceEffectController); 31 | } 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/S/ScriptEventSourceHolder.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x1290)] 4 | unsafe public struct ScriptEventSourceHolder 5 | { 6 | [System.Runtime.InteropServices.FieldOffset(0x5D8)] public BSTEventSource TESHitEvent; 7 | 8 | 9 | 10 | static public ScriptEventSourceHolder* Instance 11 | { 12 | get 13 | { 14 | var getInstance = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.ScriptEventSourceHolder.GetInstance; 15 | 16 | return getInstance(); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/S/Setting.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x18)] 4 | public struct Setting 5 | { 6 | [System.Runtime.InteropServices.FieldOffset(0x8)] public SettingValue Value; 7 | [System.Runtime.InteropServices.FieldOffset(0x10)] public System.IntPtr Name; // char* 8 | } 9 | 10 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x8)] 11 | public struct SettingValue 12 | { 13 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.Byte Byte; // bool 14 | [System.Runtime.InteropServices.FieldOffset(0x0)] public Color Color; 15 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.Int32 Int32; 16 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.IntPtr String; // char* 17 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.Single Single; 18 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.UInt32 UInt32; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/S/SettingT.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x18)] 4 | unsafe public struct SettingT 5 | { 6 | public struct GameSettingCollection 7 | { 8 | static public SettingT* ArrowBowMinTime 9 | { 10 | get 11 | { 12 | return (SettingT*)Eggstensions.Offsets.SettingT.GameSettingCollection.ArrowBowMinTime; 13 | } 14 | } 15 | 16 | static public SettingT* ArrowMinPower 17 | { 18 | get 19 | { 20 | return (SettingT*)Eggstensions.Offsets.SettingT.GameSettingCollection.ArrowMinPower; 21 | } 22 | } 23 | 24 | static public SettingT* BowDrawTime 25 | { 26 | get 27 | { 28 | return (SettingT*)Eggstensions.Offsets.SettingT.GameSettingCollection.BowDrawTime; 29 | } 30 | } 31 | } 32 | 33 | 34 | 35 | [System.Runtime.InteropServices.FieldOffset(0x0)] public Setting Setting; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/S/SpellItem.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface ISpellItem : IMagicItem 4 | { 5 | } 6 | 7 | public struct SpellItem : ISpellItem 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class ISpellItem 16 | { 17 | // Member 18 | /// SkyrimSE.exe + 0x632180 (VID 37817) 19 | static public void Apply(this ref TSpellItem spell, TActor1* caster, TActor2* target) 20 | where TSpellItem : unmanaged, Eggstensions.ISpellItem 21 | where TActor1 : unmanaged, Eggstensions.IActor 22 | where TActor2 : unmanaged, Eggstensions.IActor 23 | { 24 | if (spell.ShouldAddSpell()) 25 | { 26 | target->AddSpell(spell.AsPointer()); 27 | } 28 | else 29 | { 30 | var magicCaster = caster->GetMagicCaster(CastingSource.Instant); 31 | 32 | magicCaster->Cast(spell.AsPointer(), false, target, 1.0F, false, 0.0F, (Actor*)null); 33 | } 34 | } 35 | 36 | static public System.Boolean ShouldAddSpell(this ref TSpellItem spell) 37 | where TSpellItem : unmanaged, Eggstensions.ISpellItem 38 | { 39 | var shouldAddSpell = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.SpellItem.ShouldAddSpell; 40 | 41 | return ShouldAddSpell(spell.AsPointer()) != 0; 42 | 43 | 44 | 45 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 46 | System.Byte ShouldAddSpell(TSpellItem* spell) 47 | { 48 | return shouldAddSpell(spell); 49 | } 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/SKSE.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | namespace SKSE 4 | { 5 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x18)] 6 | public struct PluginInfo 7 | { 8 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.UInt32 InfoVersion; 9 | [System.Runtime.InteropServices.FieldOffset(0x8)] public System.IntPtr Name; 10 | [System.Runtime.InteropServices.FieldOffset(0x10)] public System.UInt32 Version; 11 | } 12 | 13 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x30)] 14 | unsafe public struct SKSEInterface 15 | { 16 | [System.Runtime.InteropServices.FieldOffset(0x0)] public System.UInt32 SKSEVersion; 17 | [System.Runtime.InteropServices.FieldOffset(0x4)] public System.UInt32 RuntimeVersion; 18 | [System.Runtime.InteropServices.FieldOffset(0x8)] public System.UInt32 EditorVersion; 19 | [System.Runtime.InteropServices.FieldOffset(0xC)] public System.UInt32 IsEditor; 20 | [System.Runtime.InteropServices.FieldOffset(0x10)] public delegate* unmanaged[Cdecl] QueryInterface; 21 | [System.Runtime.InteropServices.FieldOffset(0x18)] public delegate* unmanaged[Cdecl] GetPluginHandle; 22 | [System.Runtime.InteropServices.FieldOffset(0x20)] public delegate* unmanaged[Cdecl] GetReleaseIndex; 23 | [System.Runtime.InteropServices.FieldOffset(0x28)] public delegate* unmanaged[Cdecl] GetPluginInfo; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/T/TESActorBase.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface ITESActorBase : ITESBoundObject 4 | { 5 | } 6 | 7 | public struct TESActorBase : ITESActorBase 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class ITESActorBase 16 | { 17 | // Inheritance 18 | static public TESFullName* TESFullName(this ref TTESActorBase actorBase) 19 | where TTESActorBase : unmanaged, Eggstensions.ITESActorBase 20 | { 21 | return (TESFullName*)actorBase.AddByteOffset(0xD8); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/T/TESAmmo.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface ITESAmmo : ITESBoundObject 4 | { 5 | } 6 | 7 | public struct TESAmmo : ITESAmmo 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class ITESAmmo 16 | { 17 | // Virtual 18 | static public System.Boolean IsPlayable(this ref TTESAmmo ammo) 19 | where TTESAmmo : unmanaged, Eggstensions.ITESAmmo 20 | { 21 | var isPlayable = (delegate* unmanaged[Cdecl])ammo.VirtualFunction(0x19); 22 | 23 | return IsPlayable(ammo.AsPointer()) != 0; 24 | 25 | 26 | 27 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 28 | System.Byte IsPlayable(TTESAmmo* ammo) 29 | { 30 | return isPlayable(ammo); 31 | } 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/T/TESBoundObject.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface ITESBoundObject : ITESForm 4 | { 5 | } 6 | 7 | public struct TESBoundObject : ITESBoundObject 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/T/TESDataHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface ITESDataHandler : IUnmanagedObject 4 | { 5 | } 6 | 7 | unsafe public struct TESDataHandler : ITESDataHandler 8 | { 9 | // Static 10 | static public TESForm* GetForm(System.UInt32 formId) 11 | { 12 | var getForm = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.TESDataHandler.GetForm; 13 | 14 | return GetForm(formId); 15 | 16 | 17 | 18 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 19 | TESForm* GetForm(System.UInt32 formId) 20 | { 21 | return getForm(formId); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/T/TESForm.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public enum FormType : System.Byte 4 | { 5 | Armor = 0x1A, 6 | Tree = 0x26, 7 | Flora = 0x27, 8 | Weapon = 0x29, 9 | Actor = 0x3E 10 | } 11 | 12 | 13 | 14 | public interface ITESForm : IVirtualObject 15 | { 16 | } 17 | 18 | public struct TESForm : ITESForm 19 | { 20 | } 21 | 22 | 23 | 24 | namespace ExtensionMethods 25 | { 26 | unsafe static public class ITESForm 27 | { 28 | // Field 29 | static public System.UInt32 FormId(this ref TTESForm form) 30 | where TTESForm : unmanaged, Eggstensions.ITESForm 31 | { 32 | return *(System.UInt32*)form.AddByteOffset(0x14); 33 | } 34 | 35 | static public FormType FormType(this ref TTESForm form) 36 | where TTESForm : unmanaged, Eggstensions.ITESForm 37 | { 38 | return (FormType)(*(System.Byte*)form.AddByteOffset(0x1A)); 39 | } 40 | 41 | 42 | 43 | // Virtual 44 | static public void RemoveChanges(this ref TTESForm form, System.UInt32 changeFlags) 45 | where TTESForm : unmanaged, Eggstensions.ITESForm 46 | { 47 | var removeChanges = (delegate* unmanaged[Cdecl])form.VirtualFunction(0xB); 48 | 49 | RemoveChanges(form.AsPointer(), changeFlags); 50 | 51 | 52 | 53 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 54 | void RemoveChanges(TTESForm* form, System.UInt32 changeFlags) 55 | { 56 | removeChanges(form, changeFlags); 57 | } 58 | } 59 | 60 | 61 | 62 | // Member 63 | static public EnchantmentItem* GetEnchantment(this ref TTESForm form, ExtraDataList* extraDataList) 64 | where TTESForm : unmanaged, Eggstensions.ITESForm 65 | { 66 | var getEnchantment = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.TESForm.GetEnchantment; 67 | 68 | return GetEnchantment(form.AsPointer(), extraDataList); 69 | 70 | 71 | 72 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 73 | EnchantmentItem* GetEnchantment(TTESForm* form, ExtraDataList* extraDataList) 74 | { 75 | return getEnchantment(form, extraDataList); 76 | } 77 | } 78 | 79 | static public System.String GetFormName(this ref TTESForm form) 80 | where TTESForm : unmanaged, Eggstensions.ITESForm 81 | { 82 | var getFormName = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.TESForm.GetFormName; 83 | 84 | return Memory.ReadString(GetFormName(form.AsPointer())); 85 | 86 | 87 | 88 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 89 | System.IntPtr GetFormName(TTESForm* form) 90 | { 91 | return getFormName(form); 92 | } 93 | } 94 | 95 | static public System.UInt16 GetMaximumCharge(this ref TTESForm form, ExtraDataList* extraDataList) 96 | where TTESForm : unmanaged, Eggstensions.ITESForm 97 | { 98 | var getMaximumCharge = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.TESForm.GetMaximumCharge; 99 | 100 | return GetMaximumCharge(form.AsPointer(), extraDataList); 101 | 102 | 103 | 104 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 105 | System.UInt16 GetMaximumCharge(TTESForm* form, ExtraDataList* extraDataList) 106 | { 107 | return getMaximumCharge(form, extraDataList); 108 | } 109 | } 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/T/TESFullName.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface ITESFullName : IVirtualObject 4 | { 5 | } 6 | 7 | public struct TESFullName : ITESFullName 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class ITESFullName 16 | { 17 | // Virtual 18 | static public System.String GetFullName(this ref TTESFullName fullName) 19 | where TTESFullName : unmanaged, Eggstensions.ITESFullName 20 | { 21 | var getFullName = (delegate* unmanaged[Cdecl])fullName.VirtualFunction(0x5); 22 | 23 | return Memory.ReadString(GetFullName(fullName.AsPointer())); 24 | 25 | 26 | 27 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 28 | System.IntPtr GetFullName(TTESFullName* fullName) 29 | { 30 | return getFullName(fullName); 31 | } 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/T/TESHitEvent.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | [System.Flags] 4 | public enum TESHitEventFlags : System.Byte 5 | { 6 | None = 0, 7 | PowerAttack = 1 << 0, 8 | SneakAttack = 1 << 1, 9 | BashAttack = 1 << 2, 10 | HitBlocked = 1 << 3 11 | } 12 | 13 | 14 | 15 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x20)] 16 | unsafe public struct TESHitEvent 17 | { 18 | [System.Runtime.InteropServices.FieldOffset(0x0)] public TESObjectREFR* Target; 19 | [System.Runtime.InteropServices.FieldOffset(0x8)] public TESObjectREFR* Cause; 20 | [System.Runtime.InteropServices.FieldOffset(0x10)] public System.UInt32 Source; // FormId 21 | [System.Runtime.InteropServices.FieldOffset(0x14)] public System.UInt32 Projectile; // FormId 22 | [System.Runtime.InteropServices.FieldOffset(0x18)] public TESHitEventFlags Flags; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/T/TESNPC.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface ITESNPC : ITESActorBase 4 | { 5 | } 6 | 7 | public struct TESNPC : ITESNPC 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/T/TESObjectARMO.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface ITESObjectARMO : ITESBoundObject 4 | { 5 | } 6 | 7 | public struct TESObjectARMO : ITESObjectARMO 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class ITESObjectARMO 16 | { 17 | // Inheritance 18 | static public TESFullName* TESFullName(this ref TTESObjectARMO armor) 19 | where TTESObjectARMO : unmanaged, Eggstensions.ITESObjectARMO 20 | { 21 | return (TESFullName*)armor.AddByteOffset(0x30); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/T/TESObjectREFR.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface ITESObjectREFR : ITESForm 4 | { 5 | } 6 | 7 | public struct TESObjectREFR : ITESObjectREFR 8 | { 9 | [System.Flags] 10 | public enum ChangeFlags : System.UInt32 11 | { 12 | Empty = 1U << 21 13 | } 14 | } 15 | 16 | 17 | 18 | namespace ExtensionMethods 19 | { 20 | unsafe static public class ITESObjectREFR 21 | { 22 | // Inheritance 23 | static public BSHandleRefObject* BSHandleRefObject(this ref TTESObjectREFR reference) 24 | where TTESObjectREFR : unmanaged, Eggstensions.ITESObjectREFR 25 | { 26 | return (BSHandleRefObject*)reference.AddByteOffset(0x20); 27 | } 28 | 29 | static public IAnimationGraphManagerHolder* IAnimationGraphManagerHolder(this ref TTESObjectREFR reference) 30 | where TTESObjectREFR : unmanaged, Eggstensions.ITESObjectREFR 31 | { 32 | return (IAnimationGraphManagerHolder*)reference.AddByteOffset(0x38); 33 | } 34 | 35 | 36 | 37 | // Field 38 | static public TESBoundObject* BaseObject(this ref TTESObjectREFR reference) 39 | where TTESObjectREFR : unmanaged, Eggstensions.ITESObjectREFR 40 | { 41 | return *(TESBoundObject**)reference.AddByteOffset(0x40); 42 | } 43 | 44 | static public NiPoint3* Rotation(this ref TTESObjectREFR reference) 45 | where TTESObjectREFR : unmanaged, Eggstensions.ITESObjectREFR 46 | { 47 | return (NiPoint3*)reference.AddByteOffset(0x4C); 48 | } 49 | 50 | static public NiPoint3* Position(this ref TTESObjectREFR reference) 51 | where TTESObjectREFR : unmanaged, Eggstensions.ITESObjectREFR 52 | { 53 | return (NiPoint3*)reference.AddByteOffset(0x54); 54 | } 55 | 56 | 57 | 58 | // Virtual 59 | static public NiAVObject* GetCurrent3D(this ref TTESObjectREFR reference) 60 | where TTESObjectREFR : unmanaged, Eggstensions.ITESObjectREFR 61 | { 62 | var getCurrent3D = (delegate* unmanaged[Cdecl])reference.VirtualFunction(0x8D); 63 | 64 | return GetCurrent3D(reference.AsPointer()); 65 | 66 | 67 | 68 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 69 | NiAVObject* GetCurrent3D(TTESObjectREFR* reference) 70 | { 71 | return getCurrent3D(reference); 72 | } 73 | } 74 | 75 | 76 | 77 | // Member 78 | static public InventoryChanges* GetInventoryChanges(this ref TTESObjectREFR reference) 79 | where TTESObjectREFR : unmanaged, Eggstensions.ITESObjectREFR 80 | { 81 | var getInventoryChanges = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.TESObjectREFR.GetInventoryChanges; 82 | 83 | return GetInventoryChanges(reference.AsPointer()); 84 | 85 | 86 | 87 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 88 | InventoryChanges* GetInventoryChanges(TTESObjectREFR* reference) 89 | { 90 | return getInventoryChanges(reference); 91 | } 92 | } 93 | 94 | static public System.String GetReferenceName(this ref TTESObjectREFR reference) 95 | where TTESObjectREFR : unmanaged, Eggstensions.ITESObjectREFR 96 | { 97 | var getReferenceName = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.TESObjectREFR.GetReferenceName; 98 | 99 | return Memory.ReadString(GetReferenceName(reference.AsPointer())); 100 | 101 | 102 | 103 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 104 | System.IntPtr GetReferenceName(TTESObjectREFR* reference) 105 | { 106 | return getReferenceName(reference); 107 | } 108 | } 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/T/TESObjectWEAP.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface ITESObjectWEAP : ITESBoundObject 4 | { 5 | } 6 | 7 | public struct TESObjectWEAP : ITESObjectWEAP 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/T/TESQuest.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface ITESQuest : ITESForm 4 | { 5 | } 6 | 7 | public struct TESQuest : ITESQuest 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class ITESQuest 16 | { 17 | // Inheritance 18 | static public TESFullName* TESFullName(this ref TTESQuest quest) 19 | where TTESQuest : unmanaged, Eggstensions.ITESObjectARMO 20 | { 21 | return (TESFullName*)quest.AddByteOffset(0x28); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/T/TESRace.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface ITESRace : ITESForm 4 | { 5 | } 6 | 7 | public struct TESRace : ITESRace 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/Trampoline.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | unsafe static public class Trampoline 4 | { 5 | static private System.Int32 position = 0; 6 | 7 | 8 | 9 | static public event System.EventHandler Write; 10 | 11 | 12 | 13 | static public System.IntPtr Address { get; private set; } 14 | 15 | 16 | 17 | /// https://stackoverflow.com/a/54732489 18 | static public System.IntPtr Allocate(System.Diagnostics.ProcessModule processModule, System.Int32 size) 19 | { 20 | Memory.GetSystemInfo(out var systemInfo); 21 | 22 | var minimum = processModule.BaseAddress.ToInt64() > processModule.ModuleMemorySize - System.Int32.MinValue ? Math.Ceiling(processModule.BaseAddress + System.Int32.MinValue + processModule.ModuleMemorySize, systemInfo.AllocationGranularity) : System.IntPtr.Zero; 23 | var maximum = processModule.BaseAddress.ToInt64() < (System.Int64.MaxValue - System.Int32.MaxValue) ? Math.Floor(processModule.BaseAddress + System.Int32.MaxValue, systemInfo.AllocationGranularity) : new System.IntPtr(System.Int64.MaxValue); 24 | 25 | while (minimum.ToInt64() < maximum.ToInt64()) 26 | { 27 | if (Memory.VirtualQuery(minimum, out var memoryBasicInformation, new System.IntPtr(System.Runtime.CompilerServices.Unsafe.SizeOf())) == System.IntPtr.Zero) 28 | { 29 | return System.IntPtr.Zero; 30 | } 31 | 32 | minimum = new System.IntPtr(memoryBasicInformation.BaseAddress.ToInt64() + memoryBasicInformation.RegionSize.ToInt64()); 33 | 34 | if (memoryBasicInformation.State == MemoryBasicInformation.States.MemFree) 35 | { 36 | var baseAddress = Math.Ceiling(memoryBasicInformation.BaseAddress, systemInfo.AllocationGranularity); 37 | 38 | // If rounding has not changed regions and the region is at least the specified size 39 | if (baseAddress.ToInt64() < minimum.ToInt64() && (minimum.ToInt64() - baseAddress.ToInt64()) >= size) 40 | { 41 | var allocation = Memory.VirtualAlloc(baseAddress, new System.IntPtr(size), AllocationTypes.MemCommit | AllocationTypes.MemReserve, MemoryProtectionConstants.PageExecuteReadWrite); 42 | 43 | if (allocation != System.IntPtr.Zero) 44 | { 45 | return allocation; 46 | } 47 | } 48 | } 49 | } 50 | 51 | return System.IntPtr.Zero; 52 | } 53 | 54 | static public void CaptureContext(System.IntPtr address, delegate* unmanaged[Cdecl] function, System.Byte[] before = null, System.Byte[] after = null) 55 | { 56 | var captureContext = Assembly.CaptureContext(function, before, after); 57 | var position = Trampoline.Reserve(System.Runtime.CompilerServices.Unsafe.SizeOf() * captureContext.Length); 58 | 59 | Trampoline.Write += (System.Object sender, System.EventArgs arguments) => 60 | { 61 | Memory.SafeWrite(Trampoline.Address + position, captureContext); 62 | Memory.WriteRelativeCall(address, (Trampoline.Address + position).ToPointer()); 63 | }; 64 | } 65 | 66 | static public void CaptureContext(System.IntPtr address, System.Int32 offset, delegate* unmanaged[Cdecl] function, System.Byte[] before = null, System.Byte[] after = null) 67 | { 68 | Trampoline.CaptureContext(address + offset, function, before, after); 69 | } 70 | 71 | static public void Commit() 72 | { 73 | if (Trampoline.position > 0) 74 | { 75 | Trampoline.Address = Trampoline.Allocate(Main.MainModule, Trampoline.position); 76 | 77 | if (Trampoline.Address == System.IntPtr.Zero) 78 | { 79 | try 80 | { 81 | throw new System.InsufficientMemoryException($"{nameof(Trampoline)}: Failed to allocate {Trampoline.position:X} bytes of memory."); 82 | } 83 | catch (System.InsufficientMemoryException insufficientMemoryException) 84 | { 85 | Log.Information($"{insufficientMemoryException}"); 86 | 87 | throw; 88 | } 89 | } 90 | 91 | Trampoline.Write?.Invoke(null, System.EventArgs.Empty); 92 | } 93 | } 94 | 95 | static public void Free(System.IntPtr address) 96 | { 97 | Memory.VirtualFree(address, System.IntPtr.Zero, FreeTypes.MemRelease); 98 | } 99 | 100 | static public System.Int32 Reserve(System.Int32 size) 101 | { 102 | return System.Threading.Interlocked.Add(ref Trampoline.position, size) - size; 103 | } 104 | 105 | static public void WriteRelativeCall(System.IntPtr address, void* function) 106 | { 107 | var absoluteJump = Assembly.AbsoluteJump(function); 108 | var position = Trampoline.Reserve(System.Runtime.CompilerServices.Unsafe.SizeOf()); 109 | 110 | Trampoline.Write += (System.Object sender, System.EventArgs arguments) => 111 | { 112 | Memory.SafeWrite(Trampoline.Address + position, absoluteJump); 113 | Memory.WriteRelativeCall(address, (Trampoline.Address + position).ToPointer()); 114 | }; 115 | } 116 | 117 | static public void WriteRelativeCall(System.IntPtr address, System.Int32 offset, void* function) 118 | { 119 | Trampoline.WriteRelativeCall(address + offset, function); 120 | } 121 | 122 | static public void WriteRelativeCallBranch(System.IntPtr address, System.Byte[] assembly) 123 | { 124 | var position = Trampoline.Reserve(System.Runtime.CompilerServices.Unsafe.SizeOf() * assembly.Length); 125 | 126 | Trampoline.Write += (System.Object sender, System.EventArgs arguments) => 127 | { 128 | Memory.SafeWrite(Trampoline.Address + position, assembly); 129 | Memory.WriteRelativeCall(address, (Trampoline.Address + position).ToPointer()); 130 | }; 131 | } 132 | 133 | static public void WriteRelativeCallBranch(System.IntPtr address, System.Int32 offset, System.Byte[] assembly) 134 | { 135 | Trampoline.WriteRelativeCallBranch(address + offset, assembly); 136 | } 137 | 138 | static public void WriteRelativeJump(System.IntPtr address, void* function) 139 | { 140 | var absoluteJump = Assembly.AbsoluteJump(function); 141 | var position = Trampoline.Reserve(System.Runtime.CompilerServices.Unsafe.SizeOf()); 142 | 143 | Trampoline.Write += (System.Object sender, System.EventArgs arguments) => 144 | { 145 | Memory.SafeWrite(Trampoline.Address + position, absoluteJump); 146 | Memory.WriteRelativeJump(address, (Trampoline.Address + position).ToPointer()); 147 | }; 148 | } 149 | 150 | static public void WriteRelativeJump(System.IntPtr address, System.Int32 offset, void* function) 151 | { 152 | Trampoline.WriteRelativeJump(address + offset, function); 153 | } 154 | 155 | static public void WriteRelativeJumpBranch(System.IntPtr address, System.Byte[] assembly) 156 | { 157 | var position = Trampoline.Reserve(System.Runtime.CompilerServices.Unsafe.SizeOf() * assembly.Length); 158 | 159 | Trampoline.Write += (System.Object sender, System.EventArgs arguments) => 160 | { 161 | Memory.SafeWrite(Trampoline.Address + position, assembly); 162 | Memory.WriteRelativeJump(address, (Trampoline.Address + position).ToPointer()); 163 | }; 164 | } 165 | 166 | static public void WriteRelativeJumpBranch(System.IntPtr address, System.Int32 offset, System.Byte[] assembly) 167 | { 168 | Trampoline.WriteRelativeJumpBranch(address + offset, assembly); 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/U/UI.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IUI : IUnmanagedObject 4 | { 5 | } 6 | 7 | unsafe public struct UI : IUI 8 | { 9 | // Static 10 | static public void Notification(System.String text, System.String sound, System.Boolean queueOnce) 11 | { 12 | var notification = (delegate* unmanaged[Cdecl])Eggstensions.Offsets.UI.Notification; 13 | 14 | Notification(new UnmanagedType.LPStr { Value = text }, new UnmanagedType.LPStr { Value = sound }, (System.Byte)(queueOnce ? 1 : 0)); 15 | 16 | 17 | 18 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 19 | void Notification(UnmanagedType.LPStr text, UnmanagedType.LPStr sound, System.Byte queueOnce) 20 | { 21 | notification(text, sound, queueOnce); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/UnmanagedArray.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public class UnmanagedArray : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList 4 | where TDestination : unmanaged, System.IEquatable 5 | { 6 | private TDestination[] elements = new TDestination[0]; 7 | 8 | 9 | 10 | public TDestination this[System.Int32 index] 11 | { 12 | get 13 | { 14 | return this.elements[index]; 15 | } 16 | set 17 | { 18 | Insert(index, value); 19 | } 20 | } 21 | 22 | 23 | 24 | public System.Int32 Count 25 | { 26 | get 27 | { 28 | return this.elements.Length; 29 | } 30 | } 31 | 32 | public System.Boolean IsReadOnly 33 | { 34 | get 35 | { 36 | return false; 37 | } 38 | } 39 | 40 | 41 | 42 | static public UnmanagedArray CreateInstance(TDestination element) 43 | { 44 | var array = new UnmanagedArray(); 45 | array.Add(element); 46 | 47 | return array; 48 | } 49 | 50 | static public UnmanagedArray CreateInstance(TDestination[] elements) 51 | { 52 | var array = new UnmanagedArray(); 53 | array.Add(elements); 54 | 55 | return array; 56 | } 57 | 58 | static public UnmanagedArray CreateInstance(TSource element) 59 | where TSource : unmanaged 60 | { 61 | var array = new UnmanagedArray(); 62 | array.Add(element); 63 | 64 | return array; 65 | } 66 | 67 | static public UnmanagedArray CreateInstance(TSource[] elements) 68 | where TSource : unmanaged 69 | { 70 | var array = new UnmanagedArray(); 71 | array.Add(elements); 72 | 73 | return array; 74 | } 75 | 76 | 77 | 78 | public void Add(TDestination element) 79 | { 80 | var copy = new TDestination[this.elements.Length + 1]; 81 | 82 | for (var index = 0; index < this.elements.Length; index++) 83 | { 84 | copy[index] = this.elements[index]; 85 | } 86 | 87 | copy[this.elements.Length + 1] = element; 88 | 89 | this.elements = copy; 90 | } 91 | 92 | public void Add(TDestination[] elements) 93 | { 94 | var copy = new TDestination[this.elements.Length + elements.Length]; 95 | 96 | for (var index = 0; index < this.elements.Length; index++) 97 | { 98 | copy[index] = this.elements[index]; 99 | } 100 | 101 | for (var index = 0; index < elements.Length; index++) 102 | { 103 | copy[this.elements.Length + index] = elements[index]; 104 | } 105 | 106 | this.elements = copy; 107 | } 108 | 109 | public void Add(TSource element) 110 | where TSource : unmanaged 111 | { 112 | Add(Memory.ToArray(element)); 113 | } 114 | 115 | public void Add(TSource[] elements) 116 | where TSource : unmanaged 117 | { 118 | Add(Memory.ToArray(elements)); 119 | } 120 | 121 | public void Clear() 122 | { 123 | this.elements = new TDestination[0]; 124 | } 125 | 126 | public System.Boolean Contains(TDestination element) 127 | { 128 | for (var index = 0; index < this.elements.Length; index++) 129 | { 130 | if (this.elements[index].Equals(element)) 131 | { 132 | return true; 133 | } 134 | } 135 | 136 | return false; 137 | } 138 | 139 | public TDestination[] Copy() 140 | { 141 | var copy = new TDestination[this.elements.Length]; 142 | 143 | for (var index = 0; index < this.elements.Length; index++) 144 | { 145 | copy[index] = this.elements[index]; 146 | } 147 | 148 | return copy; 149 | } 150 | 151 | public void CopyTo(TDestination[] array, System.Int32 destinationIndex) 152 | { 153 | for (var index = 0; index < this.elements.Length; index++) 154 | { 155 | array[destinationIndex + index] = this.elements[index]; 156 | } 157 | } 158 | 159 | public System.Collections.Generic.IEnumerator GetEnumerator() 160 | { 161 | for (var index = 0; index < this.elements.Length; index++) 162 | { 163 | yield return this.elements[index]; 164 | } 165 | } 166 | 167 | System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 168 | { 169 | return GetEnumerator(); 170 | } 171 | 172 | public System.Int32 IndexOf(TDestination element) 173 | { 174 | for (var index = 0; index < this.elements.Length; index++) 175 | { 176 | if (this.elements[index].Equals(element)) 177 | { 178 | return index; 179 | } 180 | } 181 | 182 | return -1; 183 | } 184 | 185 | public void Insert(System.Int32 destinationIndex, TDestination element) 186 | { 187 | var copy = new TDestination[this.elements.Length + 1]; 188 | 189 | for (var index = 0; index < destinationIndex; index++) 190 | { 191 | copy[index] = this.elements[index]; 192 | } 193 | 194 | copy[destinationIndex] = element; 195 | 196 | for (var index = destinationIndex; index < this.elements.Length; index++) 197 | { 198 | copy[index + 1] = this.elements[index]; 199 | } 200 | 201 | this.elements = copy; 202 | } 203 | 204 | public System.Boolean Remove(TDestination element) 205 | { 206 | var index = IndexOf(element); 207 | 208 | if (index >= 0) 209 | { 210 | RemoveAt(index); 211 | 212 | return true; 213 | } 214 | 215 | return false; 216 | } 217 | 218 | public void RemoveAt(System.Int32 destinationIndex) 219 | { 220 | var copy = new TDestination[this.elements.Length - 1]; 221 | 222 | for (var index = 0; index < destinationIndex; index++) 223 | { 224 | copy[index] = this.elements[index]; 225 | } 226 | 227 | for (var index = destinationIndex; index + 1 < this.elements.Length; index++) 228 | { 229 | copy[index] = this.elements[index + 1]; 230 | } 231 | 232 | this.elements = copy; 233 | } 234 | 235 | 236 | 237 | static public implicit operator TDestination[](UnmanagedArray array) 238 | { 239 | return array.Copy(); 240 | } 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/UnmanagedObject.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IUnmanagedObject 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/UnmanagedType.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | namespace UnmanagedType 4 | { 5 | public struct LPStr 6 | { 7 | [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)] 8 | public System.String Value; 9 | } 10 | 11 | public struct LPWStr 12 | { 13 | [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] 14 | public System.String Value; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/V/ValueModifierEffect.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IValueModifierEffect : IActiveEffect 4 | { 5 | } 6 | 7 | public struct ValueModifierEffect : IValueModifierEffect 8 | { 9 | } 10 | 11 | 12 | 13 | namespace ExtensionMethods 14 | { 15 | unsafe static public class IValueModifierEffect 16 | { 17 | // Field 18 | static public ActorValue ActorValue(this ref TValueModifierEffect valueModifierEffect) 19 | where TValueModifierEffect : unmanaged, Eggstensions.IValueModifierEffect 20 | { 21 | return (ActorValue)(*(System.Int32*)valueModifierEffect.AddByteOffset(0x90)); 22 | } 23 | 24 | 25 | 26 | // Virtual 27 | static public void ModifyActorValue(this ref TValueModifierEffect valueModifierEffect, TActor* actor, System.Single magnitude, ActorValue actorValue) 28 | where TValueModifierEffect : unmanaged, Eggstensions.IValueModifierEffect 29 | where TActor : unmanaged, Eggstensions.IActor 30 | { 31 | var modifyActorValue = (delegate* unmanaged[Cdecl])valueModifierEffect.VirtualFunction(0x20); 32 | 33 | ModifyActorValue(valueModifierEffect.AsPointer(), actor, magnitude, (System.Int32)actorValue); 34 | 35 | 36 | 37 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 38 | void ModifyActorValue(TValueModifierEffect* valueModifierEffect, TActor* actor, System.Single magnitude, System.Int32 actorValue) 39 | { 40 | modifyActorValue(valueModifierEffect, actor, magnitude, actorValue); 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Eggstensions/Eggstensions/VirtualObject.cs: -------------------------------------------------------------------------------- 1 | namespace Eggstensions 2 | { 3 | public interface IVirtualObject : IUnmanagedObject 4 | { 5 | } 6 | 7 | 8 | 9 | namespace ExtensionMethods 10 | { 11 | unsafe static public class IVirtualObject 12 | { 13 | static public void* VirtualFunction(this ref TVirtualObject virtualObject, System.Int32 index) 14 | where TVirtualObject : unmanaged, Eggstensions.IVirtualObject 15 | { 16 | return (*(System.IntPtr**)virtualObject.AsPointer())[index].ToPointer(); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Build Dependencies 2 | * [.NET 5.0 SDK x64](https://dotnet.microsoft.com/download) 3 | * [DNNE](https://github.com/AaronRobinsonMSFT/DNNE) 4 | 5 | ## End-User Dependencies 6 | * [.NET 5.0 Runtime](https://dotnet.microsoft.com/download/dotnet/5.0/runtime) 7 | * Pick only one: [SSE Engine Fixes SKSE64 Preloader](https://www.nexusmods.com/skyrimspecialedition/mods/17230) or [DLL Plugin Loader](https://www.nexusmods.com/skyrimspecialedition/mods/10546) 8 | * [Address Library for SKSE Plugins](https://www.nexusmods.com/skyrimspecialedition/mods/32444) 9 | 10 | ## Credits 11 | * [.NET Script Framework](https://www.nexusmods.com/skyrimspecialedition/mods/21294) 12 | * [CommonLibSSE](https://github.com/Ryan-rsm-McKenzie/CommonLibSSE) 13 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs.json: -------------------------------------------------------------------------------- 1 | { 2 | "fixes": 3 | { 4 | "actorValuePercentage": true, /* Calculate the percentage of an actor value using both permanent and temporary modifiers. */ 5 | "applySpellPerkEntryPoints": 6 | { 7 | "arrows": true /* The kill camera will not fire the Apply Combat Hit Spell perk entry point when simulating the trajectory of an arrow. */ 8 | }, 9 | "harvestedFlags": true, /* Flora and trees are saved when they respawn. */ 10 | "hitEffectRaceCondition": true, /* Eliminate a race condition that can prevent hit effects from being applied when an actors mesh is loaded after their magic effects. */ 11 | "magicEffectConditions": true, /* Eliminate floating-point error from the elapsed time of magic effects so that updates to their conditions will not be skipped. Disable this if Bug Fixes SSE is installed and FixAbilityConditionBug is enabled. */ 12 | "magicEffectFlags": true, /* Flags are respected when scaling the duration and magnitude of a magic effect with its effectiveness. */ 13 | "modArmorWeightPerkEntryPoint": true, /* The Mod Armor Weight perk entry point will modify the weight of only worn armor. */ 14 | "quickShot": true, /* Account for the Quick Shot perk when calculating the power of an arrow fired by the player. */ 15 | "quickShotPlaybackSpeed": 2.0, /* The playback speed of the nocking animation when the player has the Quick Shot perk. */ 16 | "terrainDecals": true, /* Apply decals to terrain in cells that have been partially unloaded. */ 17 | "trainingMenuText": true, /* Display the correct cost of a lesson in the training menu when the relevant skill is buffed or debuffed. */ 18 | "weaponCharge": true /* The charge of equipped enchanted weapons can always be fully restored. */ 19 | }, 20 | "patches": 21 | { 22 | "accumulatingMagnitude": false, /* The maximum magnitude of accumulating magnitude magic effects scales with effectiveness instead of the rate of accumulation. */ 23 | "alreadyCaughtPickpocketing": false, /* Pickpocket even if you have already been caught. */ 24 | "applySpellPerkEntryPoints": 25 | { 26 | "castSpells": true, /* Spells applied by perk entry points are cast by the source on the target. */ 27 | "multipleSpells": false /* Apply any number of spells at once using perk entry points. */ 28 | }, 29 | "attachHitEffectArt": false, /* Hit effect art is attached when an actor is loaded. */ 30 | "equipBestAmmo": false, /* Automatically equip your best playable arrows or bolts when you equip a bow or crossbow. */ 31 | "leveledCharacters": false, /* Very hard leveled characters can be the same level as hard leveled characters. */ 32 | "lockpickingExperience": true, /* Earn experience each time you pick a lock. */ 33 | "multipleHitEffects": false, /* Each of a cloaking spells effects can apply hit effects. */ 34 | "pausedGameHitEffects": true, /* Apply any number of hit effects to the player while the game is paused. */ 35 | "powerAttackStamina": false, /* Power attacks and bashes can only be performed with the required stamina. */ 36 | "reflectDamage": true, /* Reflect any amount of damage. */ 37 | "teammateDifficulty": false, /* Teammates use the same difficulty multipliers as the player. */ 38 | "underfilledSoulGems": false /* Trap only souls of the appropriate size in soul gems. */ 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31702.278 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScrambledBugs", "ScrambledBugs\ScrambledBugs.csproj", "{F231D35C-6EA9-4616-B620-195E261543D2}" 7 | EndProject 8 | Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Eggstensions", "..\Eggstensions\Eggstensions\Eggstensions.shproj", "{740EFF05-9743-47CE-B6EA-09584EAF1EDF}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C8791337-81B8-41A4-A235-62F67D114936}" 11 | ProjectSection(SolutionItems) = preProject 12 | .editorconfig = .editorconfig 13 | EndProjectSection 14 | EndProject 15 | Global 16 | GlobalSection(SharedMSBuildProjectFiles) = preSolution 17 | ..\Eggstensions\Eggstensions\Eggstensions.projitems*{740eff05-9743-47ce-b6ea-09584eaf1edf}*SharedItemsImports = 13 18 | ..\Eggstensions\Eggstensions\Eggstensions.projitems*{f231d35c-6ea9-4616-b620-195e261543d2}*SharedItemsImports = 5 19 | EndGlobalSection 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Release|Any CPU = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {F231D35C-6EA9-4616-B620-195E261543D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {F231D35C-6EA9-4616-B620-195E261543D2}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {F231D35C-6EA9-4616-B620-195E261543D2}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {F231D35C-6EA9-4616-B620-195E261543D2}.Release|Any CPU.Build.0 = Release|Any CPU 29 | EndGlobalSection 30 | GlobalSection(SolutionProperties) = preSolution 31 | HideSolutionNode = FALSE 32 | EndGlobalSection 33 | GlobalSection(ExtensibilityGlobals) = postSolution 34 | SolutionGuid = {7F285C5C-AD26-4D4B-A277-96E250D1093F} 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Fixes/ActorValuePercentage.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | using Eggstensions.ExtensionMethods; 3 | 4 | 5 | 6 | namespace ScrambledBugs.Fixes 7 | { 8 | unsafe static internal class ActorValuePercentage 9 | { 10 | static public System.Boolean Fix() 11 | { 12 | if 13 | ( 14 | !ScrambledBugs.Patterns.Fixes.ActorValuePercentage.ActorValueCondition 15 | || 16 | !ScrambledBugs.Patterns.Fixes.ActorValuePercentage.ActorValueEnemyHealth 17 | || 18 | !ScrambledBugs.Patterns.Fixes.ActorValuePercentage.ActorValuePapyrus 19 | || 20 | !ScrambledBugs.Patterns.Fixes.ActorValuePercentage.HealthCondition 21 | || 22 | !ScrambledBugs.Patterns.Fixes.ActorValuePercentage.StaminaCondition 23 | ) 24 | { 25 | return false; 26 | } 27 | 28 | ActorValuePercentage.GetActorValuePercentage(); 29 | ActorValuePercentage.GetHealthPercentage(); 30 | ActorValuePercentage.GetStaminaPercentage(); 31 | 32 | return true; 33 | } 34 | 35 | 36 | 37 | static public void GetActorValuePercentage() 38 | { 39 | var getActorValuePercentage = (delegate* unmanaged[Cdecl])&GetActorValuePercentage; 40 | 41 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Fixes.ActorValuePercentage.ActorValueCondition, getActorValuePercentage); 42 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Fixes.ActorValuePercentage.ActorValueEnemyHealth, getActorValuePercentage); 43 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Fixes.ActorValuePercentage.ActorValuePapyrus, getActorValuePercentage); 44 | 45 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 46 | static System.Single GetActorValuePercentage(Actor* actor, System.Int32 actorValue) 47 | { 48 | return ActorValuePercentage.GetActorValuePercentage(actor, (ActorValue)actorValue); 49 | } 50 | } 51 | 52 | static public void GetHealthPercentage() 53 | { 54 | var getHealthPercentage = (delegate* unmanaged[Cdecl])&GetHealthPercentage; 55 | 56 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Fixes.ActorValuePercentage.HealthCondition, getHealthPercentage); 57 | 58 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 59 | static System.Single GetHealthPercentage(Actor* actor) 60 | { 61 | return ActorValuePercentage.GetActorValuePercentage(actor, ActorValue.Health); 62 | } 63 | } 64 | 65 | static public void GetStaminaPercentage() 66 | { 67 | var getStaminaPercentage = (delegate* unmanaged[Cdecl])&GetStaminaPercentage; 68 | 69 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Fixes.ActorValuePercentage.StaminaCondition, getStaminaPercentage); 70 | 71 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 72 | static System.Single GetStaminaPercentage(Actor* actor) 73 | { 74 | using var movementActor = new NiPointer(); 75 | actor->GetMovementActor(&movementActor); 76 | 77 | return ActorValuePercentage.GetActorValuePercentage((Actor*)movementActor.Reference, ActorValue.Stamina); 78 | } 79 | } 80 | 81 | 82 | 83 | static public System.Single GetActorValuePercentage(Actor* actor, ActorValue actorValue) 84 | { 85 | var permanentValue = actor->ActorValueOwner()->GetPermanentActorValue(actorValue); 86 | var temporaryValue = actor->GetActorValueModifier(ActorValueModifier.Temporary, actorValue); 87 | 88 | if (permanentValue + temporaryValue == 0.0F) 89 | { 90 | return 1.0F; 91 | } 92 | 93 | var value = actor->ActorValueOwner()->GetActorValue(actorValue); 94 | 95 | return value / (permanentValue + temporaryValue); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Fixes/ApplySpellPerkEntryPoints/Arrows.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Fixes.ApplySpellPerkEntryPoints 6 | { 7 | unsafe static internal class Arrows 8 | { 9 | static public System.Boolean Fix() 10 | { 11 | if (!ScrambledBugs.Patterns.Fixes.ApplySpellPerkEntryPoints.Arrows.ApplyCombatHitSpellArrowProjectile) 12 | { 13 | return false; 14 | } 15 | 16 | Arrows.ApplyCombatHitSpell(); 17 | 18 | return true; 19 | } 20 | 21 | 22 | 23 | static public void ApplyCombatHitSpell() 24 | { 25 | var position = Trampoline.Reserve((7 + 4 + 4 + 2) + System.Runtime.CompilerServices.Unsafe.SizeOf() + 1); 26 | 27 | Trampoline.Write += (System.Object sender, System.EventArgs arguments) => 28 | { 29 | var assembly = new UnmanagedArray(); 30 | 31 | assembly.Add(new System.Byte[7] { 0x44, 0x8B, 0x97, 0xCC, 0x01, 0x00, 0x00 }); // mov r10d, [rdi+1CC] 32 | assembly.Add(new System.Byte[4] { 0x41, 0xC1, 0xEA, 0x08 }); // shr r10d, 8 (ProjectileFlags.Is3DLoaded) 33 | assembly.Add(new System.Byte[4] { 0x41, 0xF6, 0xC2, 0x01 }); // test r10b, 1 34 | assembly.Add(new System.Byte[2] { 0x74, (System.Byte)System.Runtime.CompilerServices.Unsafe.SizeOf() }); // je E 35 | 36 | assembly.Add(Assembly.AbsoluteJump(Memory.ReadRelativeCall(ScrambledBugs.Offsets.Fixes.ApplySpellPerkEntryPoints.Arrows.ApplyCombatHitSpellArrowProjectile))); // call BGSEntryPointPerkEntry.HandleEntryPoints 37 | 38 | assembly.Add(new System.Byte[1] { Assembly.Ret }); // ret 39 | 40 | Memory.SafeWrite(Trampoline.Address + position, assembly); 41 | Memory.WriteRelativeCall(ScrambledBugs.Offsets.Fixes.ApplySpellPerkEntryPoints.Arrows.ApplyCombatHitSpellArrowProjectile, (Trampoline.Address + position).ToPointer()); 42 | 43 | // arrowProjectile != null 44 | 45 | /* 46 | ArrowProjectile* arrowProjectile; // rdi 47 | 48 | if ((arrowProjectile->Flags() & ProjectileFlags.Is3DLoaded) == ProjectileFlags.Is3DLoaded) 49 | { 50 | goto Function; 51 | } 52 | 53 | return; 54 | */ 55 | }; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Fixes/HarvestedFlags.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | using Eggstensions.ExtensionMethods; 3 | 4 | 5 | 6 | namespace ScrambledBugs.Fixes 7 | { 8 | unsafe static internal class HarvestedFlags 9 | { 10 | static public System.Boolean Fix() 11 | { 12 | if (!ScrambledBugs.Patterns.Fixes.HarvestedFlags.RemoveHarvestedFlag) 13 | { 14 | return false; 15 | } 16 | 17 | HarvestedFlags.RemoveChangeFlag(); 18 | 19 | return true; 20 | } 21 | 22 | 23 | 24 | static private delegate* unmanaged[Cdecl] setHarvestedFlag; 25 | 26 | 27 | 28 | static public void RemoveChangeFlag() 29 | { 30 | HarvestedFlags.setHarvestedFlag = (delegate* unmanaged[Cdecl])Memory.ReadRelativeCall(ScrambledBugs.Offsets.Fixes.HarvestedFlags.RemoveHarvestedFlag); 31 | 32 | var removeChangeFlag = (delegate* unmanaged[Cdecl])&RemoveChangeFlag; 33 | 34 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Fixes.HarvestedFlags.RemoveHarvestedFlag, removeChangeFlag); 35 | 36 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 37 | static void RemoveChangeFlag(TESObjectREFR* reference, System.Byte harvested) 38 | { 39 | // reference != null 40 | 41 | var formType = reference->BaseObject()->FormType(); 42 | 43 | if (formType == FormType.Flora || formType == FormType.Tree) 44 | { 45 | reference->RemoveChanges((System.UInt32)TESObjectREFR.ChangeFlags.Empty); 46 | } 47 | 48 | SetHarvestedFlag(reference, harvested); 49 | 50 | 51 | 52 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 53 | static void SetHarvestedFlag(TESObjectREFR* reference, System.Byte harvested) 54 | { 55 | HarvestedFlags.setHarvestedFlag(reference, harvested); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Fixes/HitEffectRaceCondition.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Fixes 6 | { 7 | static internal class HitEffectRaceCondition 8 | { 9 | static public System.Boolean Fix() 10 | { 11 | if (!ScrambledBugs.Patterns.Fixes.HitEffectRaceCondition.ShouldUpdate) 12 | { 13 | return false; 14 | } 15 | 16 | HitEffectRaceCondition.ShouldUpdate(); 17 | 18 | return true; 19 | } 20 | 21 | 22 | 23 | static public void ShouldUpdate() 24 | { 25 | var assembly = new UnmanagedArray(); 26 | 27 | assembly.Add(new System.Byte[1] { 0x52 }); // push rdx 28 | assembly.Add(new System.Byte[2] { 0x8B, 0xD0 }); // mov edx, eax 29 | assembly.Add(new System.Byte[3] { 0xC1, 0xEA, 0x07 }); // shr edx, 7 (ActiveEffectFlags.HasConditions) 30 | assembly.Add(new System.Byte[3] { 0xF6, 0xC2, 0x01 }); // test dl, 1 31 | assembly.Add(new System.Byte[2] { 0x75, (2 + 3 + 3 + 2) + (2 + 3 + 3) }); // jne 12 32 | 33 | assembly.Add(new System.Byte[2] { 0x8B, 0xD0 }); // mov edx, eax 34 | assembly.Add(new System.Byte[3] { 0xC1, 0xEA, 0x05 }); // shr edx, 5 (ActiveEffectFlags.ApplyingVisualEffects) 35 | assembly.Add(new System.Byte[3] { 0xF6, 0xC2, 0x01 }); // test dl, 1 36 | assembly.Add(new System.Byte[2] { 0x75, 2 + 3 + 3 }); // jne 8 37 | 38 | assembly.Add(new System.Byte[2] { 0x8B, 0xD0 }); // mov edx, eax 39 | assembly.Add(new System.Byte[3] { 0xC1, 0xEA, 0x06 }); // shr edx, 6 (ActiveEffectFlags.ApplyingSoundEffects) 40 | assembly.Add(new System.Byte[3] { 0xF6, 0xC2, 0x01 }); // test dl, 1 41 | 42 | assembly.Add(new System.Byte[1] { 0x5A }); // pop rdx 43 | assembly.Add(new System.Byte[1] { Assembly.Ret }); // ret 44 | 45 | Trampoline.WriteRelativeCallBranch(ScrambledBugs.Offsets.Fixes.HitEffectRaceCondition.ShouldUpdate, assembly); 46 | 47 | // eflags 48 | 49 | /* 50 | ActiveEffectFlags flags; // ecx 51 | 52 | return 53 | ((flags & ActiveEffectFlags.Dispelled) == ActiveEffectFlags.Dispelled) 54 | || 55 | ((flags & ActiveEffectFlags.ApplyingVisualEffects) == ActiveEffectFlags.ApplyingVisualEffects) 56 | || 57 | ((flags & ActiveEffectFlags.ApplyingSoundEffects) == ActiveEffectFlags.ApplyingSoundEffects); 58 | */ 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Fixes/MagicEffectConditions.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Fixes 6 | { 7 | static internal class MagicEffectConditions 8 | { 9 | static public System.Boolean Fix() 10 | { 11 | if (!ScrambledBugs.Patterns.Fixes.MagicEffectConditions.UpdateConditions) 12 | { 13 | return false; 14 | } 15 | 16 | MagicEffectConditions.UpdateConditions(); 17 | 18 | return true; 19 | } 20 | 21 | 22 | 23 | static public void UpdateConditions() 24 | { 25 | var assembly = new UnmanagedArray(); 26 | 27 | assembly.Add(new System.Byte[3] { 0x0F, 0x57, 0xC0 }); // xorps xmm0, xmm0 28 | assembly.Add(new System.Byte[3] { 0x0F, 0x2F, 0xC8 }); // comiss xmm1, xmm0 29 | assembly.Add(new System.Byte[2] { 0x77, 5 + 8 }); // ja D (elapsedTime <= 0.0F) 30 | 31 | assembly.Add(new System.Byte[8] { 0xF3, 0x0F, 0x11, 0xB7, 0x8C, 0x00, 0x00, 0x00 }); // movss [rdi+8C], xmm6 (padding8C = frameTime) 32 | assembly.Add(new System.Byte[5] { 0xE9, 0x6C - ((3 + 3 + 2) + (8 + 5)) + 0x87, 0x00, 0x00, 0x00 }); // jmp DE (Skip) 33 | 34 | assembly.Add(new System.Byte[8] { 0xF3, 0x0F, 0x10, 0x97, 0x8C, 0x00, 0x00, 0x00 }); // movss xmm2, [rdi+8C] 35 | assembly.Add(new System.Byte[3] { 0x0F, 0x2F, 0xD0 }); // comiss xmm2, xmm0 36 | assembly.Add(new System.Byte[2] { 0x76, (5 + 4 + 4 + 3 + 2) + (4 + 8 + 5) }); // jna 23 (padding8C > 0.0F) 37 | 38 | assembly.Add(new System.Byte[5] { 0xB9, 0x01, 0x00, 0x00, 0x00 }); // mov ecx, 1 39 | assembly.Add(new System.Byte[4] { 0xF3, 0x0F, 0x2A, 0xC1 }); // cvtsi2ss xmm0, ecx 40 | assembly.Add(new System.Byte[4] { 0xF3, 0x0F, 0x5E, 0xC3 }); // divss xmm0,xmm3 41 | assembly.Add(new System.Byte[3] { 0x0F, 0x2F, 0xC2 }); // comiss xmm0, xmm2 42 | assembly.Add(new System.Byte[2] { 0x76, (4 + 8 + 5) }); // jna 11 (activeEffectConditionUpdateInterval > padding8C) 43 | 44 | assembly.Add(new System.Byte[4] { 0xF3, 0x0F, 0x58, 0xD6 }); // addss xmm2, xmm6 45 | assembly.Add(new System.Byte[8] { 0xF3, 0x0F, 0x11, 0x97, 0x8C, 0x00, 0x00, 0x00 }); // movss [rdi+8C], xmm2 (padding8C += frameTime) 46 | assembly.Add(new System.Byte[5] { 0xE9, 0x6C - ((3 + 3 + 2) + (8 + 5) + (8 + 3 + 2) + (5 + 4 + 4 + 3 + 2) + (4 + 8 + 5)) + 0x87, 0x00, 0x00, 0x00 }); // jmp AE (Skip) 47 | 48 | assembly.Add(new System.Byte[8] { 0xF3, 0x0F, 0x11, 0xB7, 0x8C, 0x00, 0x00, 0x00 }); // movss [rdi+8C], xmm6 (padding8C = frameTime) 49 | assembly.Add(new System.Byte[2] { 0xEB, 0x6C - ((3 + 3 + 2) + (8 + 5) + (8 + 3 + 2) + (5 + 4 + 4 + 3 + 2) + (4 + 8 + 5) + (8 + 2)) }); // jmp 1D (Update) 50 | 51 | Memory.SafeFill(ScrambledBugs.Offsets.Fixes.MagicEffectConditions.UpdateConditions, 0x6C, Assembly.Nop); 52 | Memory.SafeWrite(ScrambledBugs.Offsets.Fixes.MagicEffectConditions.UpdateConditions, assembly); 53 | 54 | // ecx 55 | // eflags 56 | // xmm0 57 | // xmm2 58 | 59 | // activeEffect != null 60 | 61 | /* 62 | ActiveEffect* activeEffect; // rdi 63 | System.Single elapsedTime; // xmm1 64 | System.Single activeEffectConditionUpdateFrequency; // xmm3 65 | System.Single frameTime; // xmm6 66 | 67 | if (elapsedTime <= 0.0F) 68 | { 69 | activeEffect->Padding8C(frameTime); 70 | 71 | goto Skip; 72 | } 73 | 74 | System.Single padding8C = activeEffect->Padding8C(); 75 | 76 | if (padding8C > 0.0F) 77 | { 78 | System.Single activeEffectConditionUpdateInterval = 1.0F / activeEffectConditionUpdateFrequency; 79 | 80 | if (padding8C < activeEffectConditionUpdateInterval) 81 | { 82 | activeEffect->Padding8C(padding8C + frameTime); 83 | 84 | goto Skip; 85 | } 86 | } 87 | 88 | activeEffect->Padding8C(frameTime); 89 | 90 | goto Update; 91 | */ 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Fixes/MagicEffectFlags.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | using Eggstensions.ExtensionMethods; 3 | 4 | 5 | 6 | namespace ScrambledBugs.Fixes 7 | { 8 | unsafe static internal class MagicEffectFlags 9 | { 10 | static public System.Boolean Fix() 11 | { 12 | if 13 | ( 14 | !ScrambledBugs.Patterns.Fixes.MagicEffectFlags.ResetEffectiveness 15 | || 16 | !ScrambledBugs.Patterns.Fixes.MagicEffectFlags.SetEffectiveness 17 | ) 18 | { 19 | return false; 20 | } 21 | 22 | MagicEffectFlags.SetEffectiveness(); 23 | 24 | return true; 25 | } 26 | 27 | 28 | 29 | static public void SetEffectiveness() 30 | { 31 | var setEffectiveness = (delegate* unmanaged[Cdecl])&SetEffectiveness; 32 | 33 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Fixes.MagicEffectFlags.ResetEffectiveness, setEffectiveness); 34 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Fixes.MagicEffectFlags.SetEffectiveness, setEffectiveness); 35 | 36 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 37 | static void SetEffectiveness(ActiveEffect* activeEffect, System.Single effectiveness) 38 | { 39 | // activeEffect != null 40 | 41 | if (effectiveness == 1.0F || effectiveness < 0.0F) 42 | { 43 | return; 44 | } 45 | 46 | var flags = activeEffect->Effect()->BaseEffect->Data()->Flags; 47 | 48 | if ((flags & EffectSettingDataFlags.NoDuration) != EffectSettingDataFlags.NoDuration && (flags & EffectSettingDataFlags.PowerAffectsDuration) == EffectSettingDataFlags.PowerAffectsDuration) 49 | { 50 | activeEffect->Duration(activeEffect->Duration() * effectiveness); 51 | } 52 | 53 | if ((flags & EffectSettingDataFlags.NoMagnitude) != EffectSettingDataFlags.NoMagnitude && (flags & EffectSettingDataFlags.PowerAffectsMagnitude) == EffectSettingDataFlags.PowerAffectsMagnitude) 54 | { 55 | var oldMagnitude = activeEffect->Magnitude(); 56 | var newMagnitude = oldMagnitude * effectiveness; 57 | 58 | if (oldMagnitude > 0.0F) 59 | { 60 | if (newMagnitude < 1.0F) 61 | { 62 | newMagnitude = 1.0F; 63 | } 64 | } 65 | else 66 | { 67 | if (newMagnitude > -1.0F) 68 | { 69 | newMagnitude = -1.0F; 70 | } 71 | } 72 | 73 | activeEffect->Magnitude(newMagnitude); 74 | } 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Fixes/ModArmorWeightPerkEntryPoint.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | using Eggstensions.ExtensionMethods; 3 | 4 | 5 | 6 | namespace ScrambledBugs.Fixes 7 | { 8 | unsafe static internal class ModArmorWeightPerkEntryPoint 9 | { 10 | static public System.Boolean Fix() 11 | { 12 | if 13 | ( 14 | !ScrambledBugs.Patterns.Fixes.ModArmorWeightPerkEntryPoint.ModArmorWeightContainer 15 | || 16 | !ScrambledBugs.Patterns.Fixes.ModArmorWeightPerkEntryPoint.ModArmorWeightInventoryChanges 17 | ) 18 | { 19 | return false; 20 | } 21 | 22 | ModArmorWeightPerkEntryPoint.ModArmorWeight(); 23 | 24 | ModArmorWeightPerkEntryPoint.AddPerkEntry(); 25 | ModArmorWeightPerkEntryPoint.RemovePerkEntry(); 26 | 27 | return true; 28 | } 29 | 30 | 31 | 32 | static private delegate* unmanaged[Cdecl] addPerkEntry; 33 | static private delegate* unmanaged[Cdecl] removePerkEntry; 34 | 35 | 36 | 37 | static public void ModArmorWeight() 38 | { 39 | var modArmorWeightContainer = (delegate* unmanaged[Cdecl])&ModArmorWeightContainer; 40 | 41 | Trampoline.CaptureContext 42 | ( 43 | ScrambledBugs.Offsets.Fixes.ModArmorWeightPerkEntryPoint.ModArmorWeightContainer, 44 | modArmorWeightContainer, 45 | Memory.ReadArray 46 | ( 47 | ScrambledBugs.Offsets.Fixes.ModArmorWeightPerkEntryPoint.ModArmorWeightContainer, 48 | System.Runtime.CompilerServices.Unsafe.SizeOf() 49 | ) 50 | ); 51 | 52 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 53 | static void ModArmorWeightContainer(Context* context) 54 | { 55 | // inventoryEntryData != null 56 | // itemWeight != null 57 | // actor != null 58 | 59 | var inventoryEntryData = (InventoryEntryData*)context->Rbp.IntPtr; 60 | var item = inventoryEntryData->Item; 61 | 62 | if (item != null) 63 | { 64 | var itemWeight = *(System.Single*)(context->Rsp.IntPtr + 0xB0); 65 | 66 | if (itemWeight > 0.0F) 67 | { 68 | var actor = *(Actor**)(context->Rsp.IntPtr + 0xB8); 69 | 70 | if (actor != null) 71 | { 72 | if (item->FormType() == FormType.Armor) 73 | { 74 | var itemCount = context->Rdx.Int32 + context->Rax.Int32; // inventoryChangesItemCount + containerItemCount 75 | 76 | if (itemCount > 0) 77 | { 78 | if (inventoryEntryData->IsWorn()) 79 | { 80 | BGSEntryPointPerkEntry.HandleEntryPoints(EntryPoint.ModArmorWeight, actor, item, &itemWeight); 81 | 82 | context->Xmm7.Single += itemWeight; 83 | context->Rdx.Int32 -= 1; // inventoryChangesItemCount 84 | } 85 | } 86 | } 87 | } 88 | } 89 | } 90 | } 91 | 92 | 93 | 94 | var modArmorWeightInventoryChanges = (delegate* unmanaged[Cdecl])&ModArmorWeightInventoryChanges; 95 | 96 | Memory.SafeFill(ScrambledBugs.Offsets.Fixes.ModArmorWeightPerkEntryPoint.ModArmorWeightInventoryChanges, 5 + 9 + 4, Assembly.Nop); 97 | Trampoline.CaptureContext(ScrambledBugs.Offsets.Fixes.ModArmorWeightPerkEntryPoint.ModArmorWeightInventoryChanges, modArmorWeightInventoryChanges); 98 | 99 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 100 | static void ModArmorWeightInventoryChanges(Context* context) 101 | { 102 | // actor != null 103 | // armor != null 104 | // armorWeight != null 105 | 106 | var actor = (Actor*)context->Rdx.IntPtr; 107 | var armor = (TESObjectARMO*)context->R8.IntPtr; 108 | var armorWeight = *(System.Single*)context->R9.IntPtr; 109 | 110 | context->Xmm1.Single = armorWeight; // armorWeight 111 | 112 | BGSEntryPointPerkEntry.HandleEntryPoints(EntryPoint.ModArmorWeight, actor, armor, &armorWeight); 113 | 114 | context->Xmm6.Single += armorWeight; // totalModifiedArmorWeight 115 | } 116 | } 117 | 118 | static public void AddPerkEntry() 119 | { 120 | ModArmorWeightPerkEntryPoint.addPerkEntry = (delegate* unmanaged[Cdecl])Memory.ReadVirtualFunction(Eggstensions.Offsets.BGSEntryPointPerkEntry.VirtualFunctionTable, 0xA); 121 | 122 | var addPerkEntry = (delegate* unmanaged[Cdecl])&AddPerkEntry; 123 | 124 | Memory.WriteVirtualFunction(Eggstensions.Offsets.BGSEntryPointPerkEntry.VirtualFunctionTable, 0xA, addPerkEntry); 125 | 126 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 127 | static void AddPerkEntry(BGSPerkEntry* perkEntry, Actor* perkOwner) 128 | { 129 | AddPerkEntry(perkEntry, perkOwner); 130 | 131 | var inventoryChanges = perkOwner->GetInventoryChanges(); 132 | 133 | if (inventoryChanges != null) 134 | { 135 | inventoryChanges->ResetWeight(); 136 | } 137 | 138 | 139 | 140 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 141 | void AddPerkEntry(BGSPerkEntry* perkEntry, Actor* perkOwner) 142 | { 143 | ModArmorWeightPerkEntryPoint.addPerkEntry(perkEntry, perkOwner); 144 | } 145 | } 146 | } 147 | 148 | static public void RemovePerkEntry() 149 | { 150 | ModArmorWeightPerkEntryPoint.removePerkEntry = (delegate* unmanaged[Cdecl])Memory.ReadVirtualFunction(Eggstensions.Offsets.BGSEntryPointPerkEntry.VirtualFunctionTable, 0xB); 151 | 152 | var removePerkEntry = (delegate* unmanaged[Cdecl])&RemovePerkEntry; 153 | 154 | Memory.WriteVirtualFunction(Eggstensions.Offsets.BGSEntryPointPerkEntry.VirtualFunctionTable, 0xB, removePerkEntry); 155 | 156 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 157 | static void RemovePerkEntry(BGSPerkEntry* perkEntry, Actor* perkOwner) 158 | { 159 | RemovePerkEntry(perkEntry, perkOwner); 160 | 161 | var inventoryChanges = perkOwner->GetInventoryChanges(); 162 | 163 | if (inventoryChanges != null) 164 | { 165 | inventoryChanges->ResetWeight(); 166 | } 167 | 168 | 169 | 170 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 171 | void RemovePerkEntry(BGSPerkEntry* perkEntry, Actor* perkOwner) 172 | { 173 | ModArmorWeightPerkEntryPoint.removePerkEntry(perkEntry, perkOwner); 174 | } 175 | } 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Fixes/QuickShot.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | using Eggstensions.ExtensionMethods; 3 | 4 | 5 | 6 | namespace ScrambledBugs.Fixes 7 | { 8 | unsafe static internal class QuickShot 9 | { 10 | static public System.Boolean Fix(System.Single quickShotPlaybackSpeed) 11 | { 12 | if 13 | ( 14 | !ScrambledBugs.Patterns.Fixes.QuickShot.CreateProjectile 15 | || 16 | !ScrambledBugs.Patterns.Fixes.QuickShot.KillCamera 17 | ) 18 | { 19 | return false; 20 | } 21 | 22 | QuickShot.quickShotPlaybackSpeed = quickShotPlaybackSpeed; 23 | 24 | QuickShot.GetArrowPower(); 25 | 26 | return true; 27 | } 28 | 29 | 30 | 31 | static public System.Single quickShotPlaybackSpeed; 32 | 33 | 34 | 35 | static public void GetArrowPower() 36 | { 37 | var getArrowPower = (delegate* unmanaged[Cdecl])&GetArrowPower; 38 | 39 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Fixes.QuickShot.CreateProjectile, getArrowPower); 40 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Fixes.QuickShot.KillCamera, getArrowPower); 41 | 42 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 43 | static System.Single GetArrowPower(System.Single drawTime, System.Single bowSpeed) 44 | { 45 | if (bowSpeed <= 0.0F) 46 | { 47 | bowSpeed = 1.0F; 48 | } 49 | 50 | System.Byte animationVariable; 51 | System.Single pullTime; 52 | 53 | var player = PlayerCharacter.Instance; 54 | var arrowBowMinTime = SettingT.GameSettingCollection.ArrowBowMinTime->Setting.Value.Single; 55 | 56 | using var animationVariableName = new BSFixedString("bPerkQuickDraw"); 57 | 58 | if (player->IAnimationGraphManagerHolder()->GetAnimationVariableBool(&animationVariableName, &animationVariable) && (animationVariable != 0)) 59 | { 60 | pullTime = drawTime - (arrowBowMinTime / QuickShot.quickShotPlaybackSpeed); 61 | } 62 | else 63 | { 64 | pullTime = drawTime - arrowBowMinTime; 65 | } 66 | 67 | var arrowMinPower = SettingT.GameSettingCollection.ArrowMinPower->Setting.Value.Single; 68 | 69 | if (pullTime <= 0.0F) 70 | { 71 | return arrowMinPower; 72 | } 73 | 74 | var bowDrawTime = SettingT.GameSettingCollection.BowDrawTime->Setting.Value.Single; 75 | var maximumPullTime = (bowDrawTime - arrowBowMinTime) / bowSpeed; 76 | 77 | if (pullTime >= maximumPullTime) 78 | { 79 | return 1.0F; 80 | } 81 | else 82 | { 83 | return arrowMinPower + ((pullTime / maximumPullTime) * (1.0F - arrowMinPower)); 84 | } 85 | } 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Fixes/SpeedMultUpdates.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | using Eggstensions.ExtensionMethods; 3 | 4 | using Events = Eggstensions.Events; 5 | 6 | 7 | 8 | namespace ScrambledBugs.Fixes 9 | { 10 | unsafe static internal class SpeedMultUpdates 11 | { 12 | [System.Flags] 13 | public enum SaveManagerFlags : System.UInt32 14 | { 15 | Loaded = 1 << 1 16 | } 17 | 18 | 19 | 20 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 0x348)] 21 | public struct SaveManager 22 | { 23 | [System.Runtime.InteropServices.FieldOffset(0x340)] public SaveManagerFlags Flags; 24 | 25 | 26 | 27 | static public SaveManager* Instance 28 | { 29 | get 30 | { 31 | return *(SpeedMultUpdates.SaveManager**)ScrambledBugs.Offsets.Fixes.SpeedMultUpdates.SaveManager; 32 | } 33 | } 34 | } 35 | 36 | 37 | 38 | static public System.Boolean Fix() 39 | { 40 | Events.InitializeThread.After -= SpeedMultUpdates.OnInitializeThread; 41 | Events.InitializeThread.After += SpeedMultUpdates.OnInitializeThread; 42 | 43 | return true; 44 | } 45 | 46 | 47 | 48 | static public void OnInitializeThread(System.Object sender, System.EventArgs arguments) 49 | { 50 | Events.InitializeThread.After -= SpeedMultUpdates.OnInitializeThread; 51 | 52 | if (!ScrambledBugs.Patterns.Fixes.SpeedMultUpdates.SpeedMultSink) 53 | { 54 | return; 55 | } 56 | 57 | SpeedMultUpdates.OnSpeedMultUpdate(); 58 | } 59 | 60 | static public void OnSpeedMultUpdate() 61 | { 62 | var onSpeedMultUpdate = (delegate* unmanaged[Cdecl])&OnSpeedMultUpdate; 63 | 64 | ((delegate* unmanaged[Cdecl]*)ScrambledBugs.Offsets.Fixes.SpeedMultUpdates.ActorValueSinkFunctionTable)[(System.Int32)ActorValue.SpeedMult] = onSpeedMultUpdate; 65 | 66 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 67 | static void OnSpeedMultUpdate(Actor* actor, System.Int32 actorValue, System.Single old, System.Single delta) 68 | { 69 | // actor != null 70 | 71 | actor->RemoveMovementFlags(); 72 | 73 | var saveManager = SpeedMultUpdates.SaveManager.Instance; 74 | 75 | if (saveManager != null) 76 | { 77 | if ((saveManager->Flags & SpeedMultUpdates.SaveManagerFlags.Loaded) != SpeedMultUpdates.SaveManagerFlags.Loaded) 78 | { 79 | actor->UpdateMovementSpeed(); 80 | } 81 | } 82 | } 83 | } 84 | 85 | 86 | 87 | static public void RemoveMovementFlags(this ref TActor actor) 88 | where TActor : unmanaged, Eggstensions.IActor 89 | { 90 | var removeMovementFlags = (delegate* unmanaged[Cdecl])ScrambledBugs.Offsets.Fixes.SpeedMultUpdates.RemoveMovementFlags; 91 | 92 | RemoveMovementFlags(actor.AsPointer()); 93 | 94 | 95 | 96 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 97 | void RemoveMovementFlags(TActor* actor) 98 | { 99 | removeMovementFlags(actor); 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Fixes/TerrainDecals.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Fixes 6 | { 7 | static internal class TerrainDecals 8 | { 9 | static public System.Boolean Fix() 10 | { 11 | if (!ScrambledBugs.Patterns.Fixes.TerrainDecals.UnloadHavokData) 12 | { 13 | return false; 14 | } 15 | 16 | Memory.SafeWrite(ScrambledBugs.Offsets.Fixes.TerrainDecals.UnloadHavokData, new System.Byte[5] { Assembly.Ret, Assembly.Nop, Assembly.Nop, Assembly.Nop, Assembly.Nop }); 17 | 18 | return true; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Fixes/TrainingMenuText.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Fixes 6 | { 7 | static internal class TrainingMenuText 8 | { 9 | static public System.Boolean Fix() 10 | { 11 | if (!ScrambledBugs.Patterns.Fixes.TrainingMenuText.GetPermanentActorValue) 12 | { 13 | return false; 14 | } 15 | 16 | Memory.SafeWrite(ScrambledBugs.Offsets.Fixes.TrainingMenuText.GetPermanentActorValue, new System.Byte?[3] { null, null, 0x18 }); 17 | 18 | return true; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Fixes/WeaponCharge.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | using Eggstensions.ExtensionMethods; 3 | 4 | 5 | 6 | namespace ScrambledBugs.Fixes 7 | { 8 | unsafe static internal class WeaponCharge 9 | { 10 | static public System.Boolean Fix() 11 | { 12 | if 13 | ( 14 | !ScrambledBugs.Patterns.Fixes.WeaponCharge.Enchant 15 | || 16 | !ScrambledBugs.Patterns.Fixes.WeaponCharge.Equip 17 | || 18 | !ScrambledBugs.Patterns.Fixes.WeaponCharge.Recharge 19 | ) 20 | { 21 | return false; 22 | } 23 | 24 | WeaponCharge.HandleEquippedItem(); 25 | 26 | return true; 27 | } 28 | 29 | 30 | 31 | static public void HandleEquippedItem() 32 | { 33 | var handleEquippedItem = (delegate* unmanaged[Cdecl])&HandleEquippedItem; 34 | 35 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Fixes.WeaponCharge.Enchant, handleEquippedItem); 36 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Fixes.WeaponCharge.Equip, handleEquippedItem); 37 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Fixes.WeaponCharge.Recharge, handleEquippedItem); 38 | 39 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 40 | static void HandleEquippedItem(Actor* actor, TESBoundObject* item, ExtraDataList* extraDataList, System.Byte leftHand) 41 | { 42 | if (item == null) 43 | { 44 | return; 45 | } 46 | 47 | var player = PlayerCharacter.Instance; 48 | var rightHand = leftHand == 0; 49 | 50 | if (actor == player) 51 | { 52 | player->RemoveEquippedItemFlags((System.Byte)((rightHand ? 1 : 0) + 1)); 53 | } 54 | 55 | var enchantment = item->GetEnchantment(extraDataList); 56 | 57 | if (enchantment == null) 58 | { 59 | return; 60 | } 61 | 62 | var castingType = enchantment->GetCastingType(); 63 | 64 | if (castingType == CastingType.ConstantEffect) 65 | { 66 | return; 67 | } 68 | 69 | var actorValue = enchantment->GetCostActorValue(rightHand); 70 | 71 | if (actorValue != ActorValue.None) 72 | { 73 | actor->RemoveActorValueModifiers(actorValue); 74 | 75 | var maximumCharge = item->GetMaximumCharge(extraDataList); 76 | actor->ActorValueOwner()->SetActorValue(actorValue, maximumCharge); 77 | 78 | if (extraDataList != null && extraDataList->HasExtraData(ExtraDataType.Charge)) 79 | { 80 | var charge = extraDataList->GetCharge(); 81 | actor->ActorValueOwner()->RestoreActorValue(ActorValueModifier.Damage, actorValue, -(maximumCharge - charge)); 82 | } 83 | } 84 | 85 | actor->RevertSelectedSpell((EquipType)(rightHand ? 1 : 0), enchantment); 86 | } 87 | } 88 | 89 | 90 | 91 | static public void RemoveEquippedItemFlags(this ref TPlayerCharacter player, System.Byte flags) 92 | where TPlayerCharacter : unmanaged, IPlayerCharacter 93 | { 94 | var removeEquippedItemFlags = (delegate* unmanaged[Cdecl])ScrambledBugs.Offsets.Fixes.WeaponCharge.RemoveEquippedItemFlags; 95 | 96 | RemoveEquippedItemFlags(player.AsPointer(), flags); 97 | 98 | 99 | 100 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 101 | void RemoveEquippedItemFlags(TPlayerCharacter* player, System.Byte flags) 102 | { 103 | removeEquippedItemFlags(player, flags); 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Patches/AccumulatingMagnitude.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Patches 6 | { 7 | unsafe static internal class AccumulatingMagnitude 8 | { 9 | static public System.Boolean Patch() 10 | { 11 | if 12 | ( 13 | !ScrambledBugs.Patterns.Patches.AccumulatingMagnitude.GetMaximumMagnitude 14 | || 15 | !ScrambledBugs.Patterns.Patches.AccumulatingMagnitude.GetMaximumMagnitudeAndRate 16 | || 17 | !ScrambledBugs.Patterns.Patches.AccumulatingMagnitude.GetMaximumWardPower 18 | || 19 | !ScrambledBugs.Patterns.Patches.AccumulatingMagnitude.SetMaximumMagnitude 20 | || 21 | !ScrambledBugs.Patterns.Patches.AccumulatingMagnitude.SetRate 22 | ) 23 | { 24 | return false; 25 | } 26 | 27 | Memory.SafeFill(ScrambledBugs.Offsets.Patches.AccumulatingMagnitude.SetMaximumMagnitude, 8, Assembly.Nop); 28 | 29 | AccumulatingMagnitude.SetRate(); 30 | AccumulatingMagnitude.GetMaximumMagnitude(); 31 | AccumulatingMagnitude.GetMaximumMagnitudeAndRate(); 32 | AccumulatingMagnitude.GetMaximumWardPower(); 33 | 34 | return true; 35 | } 36 | 37 | 38 | 39 | static public void SetRate() 40 | { 41 | var assembly = new UnmanagedArray(); 42 | 43 | assembly.Add(new System.Byte[3] { 0x0F, 0x28, 0xD0 }); // movaps xmm2, xmm0 44 | assembly.Add(new System.Byte[5] { 0xF3, 0x0F, 0x10, 0x4F, 0x78 }); // movss xmm1, [rdi+78] 45 | assembly.Add(new System.Byte[6] { 0x8B, 0x8F, 0x90, 0x00, 0x00, 0x00 }); // mov ecx, [rdi+90] 46 | assembly.Add(Assembly.RelativeCall(ScrambledBugs.Offsets.Patches.AccumulatingMagnitude.SetRate, 3 + 5 + 6, Memory.ReadRelativeCall(ScrambledBugs.Offsets.Patches.AccumulatingMagnitude.SetRate, 3 + 8 + 6))); // call AccumulatingValueModifierEffect.GetRate 47 | 48 | assembly.Add(new System.Byte[8] { 0xF3, 0x0F, 0x11, 0x87, 0x9C, 0x00, 0x00, 0x00 }); // movss [rdi+9C], xmm0 49 | 50 | Memory.SafeWrite(ScrambledBugs.Offsets.Patches.AccumulatingMagnitude.SetRate, assembly); 51 | 52 | /* 53 | AccumulatingValueModifierEffect* accumulatingValueModifierEffect; // rdi 54 | System.Single magicSkill; // xmm0 55 | 56 | accumulatingValueModifierEffect->MaximumMagnitude 57 | ( 58 | AccumulatingValueModifierEffect.GetRate 59 | ( 60 | accumulatingValueModifierEffect->ActorValue(), 61 | accumulatingValueModifierEffect->Magnitude(), 62 | magicSkill 63 | ) 64 | ); 65 | */ 66 | } 67 | 68 | static public void GetMaximumMagnitude() 69 | { 70 | var assembly = new UnmanagedArray(); 71 | 72 | assembly.Add(new System.Byte[3] { 0x48, 0x8B, 0xCB }); // mov rcx, rbx 73 | assembly.Add(Assembly.RelativeCall(ScrambledBugs.Offsets.Patches.AccumulatingMagnitude.GetMaximumMagnitude, 3, Eggstensions.Offsets.ActiveEffect.GetCurrentMagnitude.ToPointer())); // call ActiveEffect.GetCurrentMagnitude 74 | 75 | Memory.SafeWrite(ScrambledBugs.Offsets.Patches.AccumulatingMagnitude.GetMaximumMagnitude, assembly); 76 | 77 | /* 78 | AccumulatingValueModifierEffect* accumulatingValueModifierEffect; // rbx 79 | System.Single maximumMagnitude; // xmm0 80 | 81 | var maximumMagnitude = accumulatingValueModifierEffect->GetCurrentMagnitude(); 82 | */ 83 | } 84 | 85 | static public void GetMaximumMagnitudeAndRate() 86 | { 87 | var assembly = new UnmanagedArray(); 88 | 89 | assembly.Add(new System.Byte[8] { 0xF3, 0x0F, 0x10, 0xB3, 0x9C, 0x00, 0x00, 0x00 }); // movss xmm6, [rbx+9C] 90 | assembly.Add(new System.Byte[4] { 0xF3, 0x0F, 0x59, 0xF7 }); // mulss xmm6, xmm7 91 | assembly.Add(new System.Byte[3] { 0x0F, 0x28, 0xF8 }); // movaps xmm7,xmm0 92 | 93 | Memory.SafeWrite(ScrambledBugs.Offsets.Patches.AccumulatingMagnitude.GetMaximumMagnitudeAndRate, assembly); 94 | 95 | /* 96 | AccumulatingValueModifierEffect* accumulatingValueModifierEffect; // rbx 97 | System.Single frameTime; // xmm7 98 | System.Single maximumMagnitude; // xmm0 99 | 100 | var rate = accumulatingValueModifierEffect->MaximumMagnitude() * frameTime; 101 | var maximumMagnitude = accumulatingValueModifierEffect->GetCurrentMagnitude(); 102 | */ 103 | } 104 | 105 | static public void GetMaximumWardPower() 106 | { 107 | var assembly = new UnmanagedArray(); 108 | 109 | assembly.Add(new System.Byte[1] { 0x51 }); // push rcx 110 | assembly.Add(new System.Byte[4] { 0x48, 0x83, 0xEC, 0x40 }); // sub rsp, 40 111 | assembly.Add(new System.Byte[2] { 0x48, 0xB8 }); assembly.Add(Eggstensions.Offsets.FindMaxMagnitudeVisitor.VirtualFunctionTable); // mov rax 112 | assembly.Add(new System.Byte[5] { 0x48, 0x89, 0x44, 0x24, 0x20 }); // mov [rsp+20], rax 113 | assembly.Add(new System.Byte[2] { 0x31, 0xC0 }); // xor eax, eax 114 | assembly.Add(new System.Byte[5] { 0x48, 0x89, 0x44, 0x24, 0x28 }); // mov [rsp+28], rax 115 | assembly.Add(new System.Byte[5] { 0xB8, 0xFF, 0xFF, 0xFF, 0xFF }); // mov eax, -1 116 | assembly.Add(new System.Byte[4] { 0xF3, 0x0F, 0x2A, 0xC0 }); // cvtsi2ss xmm0, eax 117 | assembly.Add(new System.Byte[6] { 0xF3, 0x0F, 0x11, 0x44, 0x24, 0x30 }); // movss [rsp+30], xmm0 118 | assembly.Add(new System.Byte[5] { 0x48, 0x8D, 0x54, 0x24, 0x20 }); // lea rdx, [rsp+20] 119 | assembly.Add(new System.Byte[7] { 0x48, 0x81, 0xC1, 0x98, 0x00, 0x00, 0x00 }); // add rcx, 98 120 | assembly.Add(Assembly.AbsoluteCall(Eggstensions.Offsets.MagicTarget.VisitActiveEffects.ToPointer())); // call MagicTarget.VisitActiveEffects 121 | 122 | assembly.Add(new System.Byte[6] { 0xF3, 0x0F, 0x10, 0x4C, 0x24, 0x30 }); // movss xmm1, [rsp+30] 123 | assembly.Add(new System.Byte[5] { 0x48, 0x8B, 0x4C, 0x24, 0x40 }); // mov rcx, [rsp+40] 124 | assembly.Add(Assembly.AbsoluteCall(Eggstensions.Offsets.Actor.SetMaximumWardPower.ToPointer())); // call Actor.SetMaximumWardPower 125 | 126 | assembly.Add(new System.Byte[5] { 0x48, 0x8B, 0x4C, 0x24, 0x40 }); // mov rcx, [rsp+40] 127 | assembly.Add(Assembly.AbsoluteCall(Memory.ReadRelativeCall(ScrambledBugs.Offsets.Patches.AccumulatingMagnitude.GetMaximumWardPower))); // call Actor.GetMaximumWardPower 128 | 129 | assembly.Add(new System.Byte[4] { 0x48, 0x83, 0xC4, 0x48 }); // add rsp, 48 130 | assembly.Add(new System.Byte[1] { Assembly.Ret }); // ret 131 | 132 | Trampoline.WriteRelativeCallBranch(ScrambledBugs.Offsets.Patches.AccumulatingMagnitude.GetMaximumWardPower, assembly); 133 | 134 | /* 135 | Actor* actor; // rcx 136 | 137 | var findMaxMagnitudeVisitor = new FindMaxMagnitudeVisitor(); 138 | *(System.IntPtr*)&findMaxMagnitudeVisitor = Eggstensions.Offsets.FindMaxMagnitudeVisitor.VirtualFunctionTable; 139 | findMaxMagnitudeVisitor.FinishedActiveEffect = null; 140 | findMaxMagnitudeVisitor.MaximumMagnitude = -1.0F; 141 | 142 | actor->MagicTarget()->VisitActiveEffects(&findMaxMagnitudeVisitor); 143 | actor->SetMaximumWardPower(findMaxMagnitudeVisitor.MaximumMagnitude); 144 | 145 | return actor->GetMaximumWardPower(); 146 | */ 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Patches/AlreadyCaughtPickpocketing.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Patches 6 | { 7 | static internal class AlreadyCaughtPickpocketing 8 | { 9 | static public System.Boolean Patch() 10 | { 11 | if 12 | ( 13 | !ScrambledBugs.Patterns.Patches.AlreadyCaughtPickpocketing.IsAttackingOnSight 14 | || 15 | !ScrambledBugs.Patterns.Patches.AlreadyCaughtPickpocketing.IsNotKnockedDown 16 | ) 17 | { 18 | return false; 19 | } 20 | 21 | Memory.SafeFill(ScrambledBugs.Offsets.Patches.AlreadyCaughtPickpocketing.IsAttackingOnSight, 2, Assembly.Nop); 22 | Memory.SafeWrite(ScrambledBugs.Offsets.Patches.AlreadyCaughtPickpocketing.IsNotKnockedDown, new System.Byte?[2] { 0xEB, null }); 23 | 24 | return true; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Patches/ApplySpellPerkEntryPoints/CastSpells.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | using Eggstensions.ExtensionMethods; 3 | 4 | 5 | 6 | namespace ScrambledBugs.Patches.ApplySpellPerkEntryPoints 7 | { 8 | unsafe static internal class CastSpells 9 | { 10 | static public System.Boolean Patch() 11 | { 12 | if 13 | ( 14 | !ScrambledBugs.Patterns.Patches.ApplySpellPerkEntryPoints.CastSpells.ApplyBashingSpell 15 | || 16 | !ScrambledBugs.Patterns.Patches.ApplySpellPerkEntryPoints.CastSpells.ApplyCombatHitSpell 17 | || 18 | !ScrambledBugs.Patterns.Patches.ApplySpellPerkEntryPoints.CastSpells.ApplyCombatHitSpellArrowProjectile 19 | || 20 | !ScrambledBugs.Patterns.Patches.ApplySpellPerkEntryPoints.CastSpells.ApplyReanimateSpell 21 | || 22 | !ScrambledBugs.Patterns.Patches.ApplySpellPerkEntryPoints.CastSpells.ApplyWeaponSwingSpell 23 | ) 24 | { 25 | return false; 26 | } 27 | 28 | CastSpells.ApplySpell(); 29 | 30 | return true; 31 | } 32 | 33 | 34 | 35 | static public void ApplySpell() 36 | { 37 | var applySpell = (delegate* unmanaged[Cdecl])&ApplySpell; 38 | 39 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Patches.ApplySpellPerkEntryPoints.CastSpells.ApplyBashingSpell, applySpell); 40 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Patches.ApplySpellPerkEntryPoints.CastSpells.ApplyCombatHitSpell, applySpell); 41 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Patches.ApplySpellPerkEntryPoints.CastSpells.ApplyCombatHitSpellArrowProjectile, applySpell); 42 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Patches.ApplySpellPerkEntryPoints.CastSpells.ApplyReanimateSpell, applySpell); 43 | Trampoline.WriteRelativeCall(ScrambledBugs.Offsets.Patches.ApplySpellPerkEntryPoints.CastSpells.ApplyWeaponSwingSpell, applySpell); 44 | 45 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 46 | static void ApplySpell(Actor* target, SpellItem* spell, Actor* caster) 47 | { 48 | // target != null 49 | // spell != null 50 | // caster != null 51 | 52 | spell->Apply(caster, target); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Patches/AttachHitEffectArt.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Patches 6 | { 7 | static internal class AttachHitEffectArt 8 | { 9 | static public System.Boolean Patch() 10 | { 11 | if 12 | ( 13 | !ScrambledBugs.Patterns.Patches.AttachHitEffectArt.AddNoHitEffectArtFlag 14 | || 15 | !ScrambledBugs.Patterns.Patches.AttachHitEffectArt.IsPerspectiveChange 16 | || 17 | !ScrambledBugs.Patterns.Patches.AttachHitEffectArt.IsPlayerAttach 18 | || 19 | !ScrambledBugs.Patterns.Patches.AttachHitEffectArt.IsPlayerUpdatePosition 20 | ) 21 | { 22 | return false; 23 | } 24 | 25 | 26 | 27 | Memory.SafeFill(ScrambledBugs.Offsets.Patches.AttachHitEffectArt.IsPlayerUpdatePosition, 2, Assembly.Nop); 28 | Memory.SafeFill(ScrambledBugs.Offsets.Patches.AttachHitEffectArt.IsPerspectiveChange, 2, Assembly.Nop); 29 | 30 | AttachHitEffectArt.AddNoHitEffectArtFlag(); 31 | AttachHitEffectArt.ShouldAttach(); 32 | 33 | return true; 34 | } 35 | 36 | 37 | 38 | static public void AddNoHitEffectArtFlag() 39 | { 40 | var assembly = new UnmanagedArray(); 41 | 42 | assembly.Add(new System.Byte[2] { 0x24, 0xF8 }); // and al, F8 (1 << 2 (NoHitEffectArt), 1 << 4 (NoInitialFlare)) 43 | assembly.Add(new System.Byte[1] { Assembly.Nop }); // nop 44 | assembly.Add(new System.Byte[1] { Assembly.Nop }); // nop 45 | 46 | Memory.SafeWrite(ScrambledBugs.Offsets.Patches.AttachHitEffectArt.AddNoHitEffectArtFlag, assembly); 47 | } 48 | 49 | static public void ShouldAttach() 50 | { 51 | var assemblyBranch = new UnmanagedArray(); 52 | 53 | assemblyBranch.Add(new System.Byte[2] { 0x41, 0x54 }); // push r12 54 | assemblyBranch.Add(new System.Byte[2] { 0x41, 0x55 }); // push r13 55 | assemblyBranch.Add(new System.Byte[4] { 0x48, 0x83, 0xEC, 0x28 }); // sub rsp, 28 56 | assemblyBranch.Add(new System.Byte[4] { 0x48, 0x8B, 0x4E, 0x30 }); // mov rcx, [rsi+30] (modelReferenceEffect->Controller) 57 | assemblyBranch.Add(new System.Byte[3] { 0x48, 0x8B, 0x01 }); // mov rax, [rcx] 58 | assemblyBranch.Add(new System.Byte[3] { 0xFF, 0x50, 0x78 }); // call [rax+78] (ReferenceEffectController.GetAttachRoot(controller)) 59 | assemblyBranch.Add(new System.Byte[3] { 0x48, 0x85, 0xC0 }); // test rax, rax (attachRoot) 60 | assemblyBranch.Add(new System.Byte[2] { 0x75, 3 + 3 + 6 }); // jnz C (attachRoot == null) 61 | 62 | assemblyBranch.Add(new System.Byte[3] { 0x48, 0x8B, 0xCB }); // mov rcx, rbx (actor) 63 | assemblyBranch.Add(new System.Byte[3] { 0x48, 0x8B, 0x01 }); // mov rax, [rcx] 64 | assemblyBranch.Add(new System.Byte[6] { 0xFF, 0x90, 0x68, 0x04, 0x00, 0x00 }); // call [rax+468] (TESObjectREFR.GetCurrent3D(actor)) 65 | 66 | assemblyBranch.Add(new System.Byte[3] { 0x45, 0x31, 0xE4 }); // xor r12d, r12d (attachRootNode) 67 | assemblyBranch.Add(new System.Byte[3] { 0x48, 0x85, 0xC0 }); // test rax, rax 68 | assemblyBranch.Add(new System.Byte[2] { 0x74, (3 + 3 + 3 + 3 + 3 + 3 + 2) + 4 }); // jz 18 (attachRoot != null) 69 | 70 | assemblyBranch.Add(new System.Byte[3] { 0x4C, 0x8B, 0xE8 }); // mov r13, rax 71 | assemblyBranch.Add(new System.Byte[3] { 0x48, 0x8B, 0xC8 }); // mov rcx, rax 72 | assemblyBranch.Add(new System.Byte[3] { 0x48, 0x8B, 0x01 }); // mov rax, [rcx] 73 | assemblyBranch.Add(new System.Byte[3] { 0xFF, 0x50, 0x18 }); // call [rax+18] (NiObject.AsNode(attachRoot)) 74 | assemblyBranch.Add(new System.Byte[3] { 0x4C, 0x8B, 0xE0 }); // mov r12, rax 75 | assemblyBranch.Add(new System.Byte[3] { 0x4D, 0x85, 0xE4 }); // test r12, r12 76 | assemblyBranch.Add(new System.Byte[2] { 0x75, 4 }); // jnz 4 (attachRootNode == null) 77 | 78 | assemblyBranch.Add(new System.Byte[4] { 0x4D, 0x8B, 0x65, 0x30 }); // mov r12, [r13+30] (attachRoot->Parent) 79 | 80 | assemblyBranch.Add(new System.Byte[4] { 0x4C, 0x3B, 0x66, 0x70 }); // cmp r12, [rsi+70] 81 | assemblyBranch.Add(new System.Byte[3] { 0x0F, 0x95, 0xC0 }); // setne al (attachRootNode != modelReferenceEffect->HitEffectArtData.AttachRoot) 82 | assemblyBranch.Add(new System.Byte[4] { 0x48, 0x83, 0xC4, 0x28 }); // add rsp, 28 83 | assemblyBranch.Add(new System.Byte[2] { 0x41, 0x5D }); // pop r13 84 | assemblyBranch.Add(new System.Byte[2] { 0x41, 0x5C }); // pop r12 85 | assemblyBranch.Add(new System.Byte[1] { Assembly.Ret }); // ret 86 | 87 | Trampoline.WriteRelativeCallBranch(ScrambledBugs.Offsets.Patches.AttachHitEffectArt.IsPlayerAttach, assemblyBranch); 88 | 89 | // Volatile registers 90 | 91 | // actor != null 92 | // modelReferenceEffect != null 93 | // modelReferenceEffect->Controller != null 94 | 95 | /* 96 | ModelReferenceEffect* modelReferenceEffect; // rsi 97 | Actor* actor; // rbx 98 | 99 | ReferenceEffectController* controller = modelReferenceEffect->Controller(); 100 | NiAVObject* attachRoot = controller->GetAttachRoot(); 101 | 102 | if (attachRoot == null) 103 | { 104 | attachRoot = actor->GetCurrent3D(); 105 | } 106 | 107 | NiNode* attachRootNode = null; 108 | 109 | if (attachRoot != null) 110 | { 111 | attachRootNode = attachRoot->AsNode(); 112 | 113 | if (attachRootNode == null) 114 | { 115 | attachRootNode = attachRoot->Parent(); 116 | } 117 | } 118 | 119 | return attachRootNode != modelReferenceEffect->HitEffectArtData()->AttachRoot(); 120 | */ 121 | 122 | 123 | 124 | var assembly = new UnmanagedArray(); 125 | 126 | assembly.Add(new System.Byte[2] { 0x84, 0xC0 }); // test al, al 127 | assembly.Add(new System.Byte[2] { 0x74, 0x55 }); // jz 55 128 | 129 | Memory.SafeWrite(ScrambledBugs.Offsets.Patches.AttachHitEffectArt.IsPlayerAttach, System.Runtime.CompilerServices.Unsafe.SizeOf(), assembly); 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Patches/EquipBestAmmo.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | using Eggstensions.ExtensionMethods; 3 | 4 | 5 | 6 | namespace ScrambledBugs.Patches 7 | { 8 | unsafe static internal class EquipBestAmmo 9 | { 10 | static public System.Boolean Patch() 11 | { 12 | if 13 | ( 14 | !ScrambledBugs.Patterns.Patches.EquipBestAmmo.CompareDamageContainer 15 | || 16 | !ScrambledBugs.Patterns.Patches.EquipBestAmmo.CompareDamageInventoryChanges 17 | || 18 | !ScrambledBugs.Patterns.Patches.EquipBestAmmo.InitializeDamage 19 | ) 20 | { 21 | return false; 22 | } 23 | 24 | EquipBestAmmo.InitializeDamage(); 25 | EquipBestAmmo.CompareDamage(); 26 | 27 | return true; 28 | } 29 | 30 | 31 | 32 | static public void InitializeDamage() 33 | { 34 | var initializeDamage = (delegate* unmanaged[Cdecl])&InitializeDamage; 35 | 36 | Memory.SafeFill(ScrambledBugs.Offsets.Patches.EquipBestAmmo.InitializeDamage, 8, Assembly.Nop); 37 | Trampoline.CaptureContext(ScrambledBugs.Offsets.Patches.EquipBestAmmo.InitializeDamage, initializeDamage); 38 | 39 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 40 | static void InitializeDamage(Context* context) 41 | { 42 | context->Xmm6.Single = System.Single.MinValue; 43 | } 44 | } 45 | 46 | static public void CompareDamage() 47 | { 48 | var compareDamageContainer = (delegate* unmanaged[Cdecl])&CompareDamageContainer; 49 | 50 | Trampoline.CaptureContext(ScrambledBugs.Offsets.Patches.EquipBestAmmo.CompareDamageContainer, compareDamageContainer); 51 | 52 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 53 | static void CompareDamageContainer(Context* context) 54 | { 55 | var damage = context->Xmm0.Single; 56 | var highestDamage = context->Xmm6.Single; 57 | 58 | if (damage > highestDamage) 59 | { 60 | var ammo = (TESAmmo*)context->R8.IntPtr; 61 | 62 | if (ammo->IsPlayable()) 63 | { 64 | return; 65 | } 66 | } 67 | 68 | context->Rip.IntPtr += 0x6; 69 | } 70 | 71 | 72 | 73 | var compareDamageInventoryChanges = (delegate* unmanaged[Cdecl])&CompareDamageInventoryChanges; 74 | 75 | Trampoline.CaptureContext(ScrambledBugs.Offsets.Patches.EquipBestAmmo.CompareDamageInventoryChanges, compareDamageInventoryChanges); 76 | 77 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 78 | static void CompareDamageInventoryChanges(Context* context) 79 | { 80 | var damage = context->Xmm0.Single; 81 | var highestDamage = context->Xmm6.Single; 82 | 83 | if (damage > highestDamage) 84 | { 85 | var ammo = (TESAmmo*)context->Rbp.IntPtr; 86 | 87 | if (ammo->IsPlayable()) 88 | { 89 | return; 90 | } 91 | } 92 | 93 | context->Rip.IntPtr += 0x10; 94 | } 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Patches/LeveledCharacters.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Patches 6 | { 7 | static internal class LeveledCharacters 8 | { 9 | static public System.Boolean Patch() 10 | { 11 | if (!ScrambledBugs.Patterns.Patches.LeveledCharacters.IsVeryHard) 12 | { 13 | return false; 14 | } 15 | 16 | Memory.SafeFill(ScrambledBugs.Offsets.Patches.LeveledCharacters.IsVeryHard, 2, Assembly.Nop); 17 | 18 | return true; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Patches/LockpickingExperience.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Patches 6 | { 7 | static internal class LockpickingExperience 8 | { 9 | static public System.Boolean Patch() 10 | { 11 | if (!ScrambledBugs.Patterns.Patches.LockpickingExperience.HasNotBeenUnlocked) 12 | { 13 | return false; 14 | } 15 | 16 | Memory.SafeFill(ScrambledBugs.Offsets.Patches.LockpickingExperience.HasNotBeenUnlocked, 2, Assembly.Nop); 17 | 18 | return true; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Patches/MultipleHitEffects.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Patches 6 | { 7 | static internal class MultipleHitEffects 8 | { 9 | static public System.Boolean Patch() 10 | { 11 | if (!ScrambledBugs.Patterns.Patches.MultipleHitEffects.IsNotCostliestEffect) 12 | { 13 | return false; 14 | } 15 | 16 | Memory.SafeWrite(ScrambledBugs.Offsets.Patches.MultipleHitEffects.IsNotCostliestEffect, new System.Byte?[2] { 0xEB, null }); // 1 << 1 (NoHitShader), 1 << 2 (NoHitEffectArt), 1 << 3 17 | 18 | return true; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Patches/PausedGameHitEffects.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Patches 6 | { 7 | static internal class PausedGameHitEffects 8 | { 9 | static public System.Boolean Patch() 10 | { 11 | if (!ScrambledBugs.Patterns.Patches.PausedGameHitEffects.IsNotApplyingHitEffects) 12 | { 13 | return false; 14 | } 15 | 16 | Memory.SafeFill(ScrambledBugs.Offsets.Patches.PausedGameHitEffects.IsNotApplyingHitEffects, 2, Assembly.Nop); 17 | 18 | return true; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Patches/PowerAttackStamina.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Patches 6 | { 7 | unsafe static internal class PowerAttackStamina 8 | { 9 | static public System.Boolean Patch() 10 | { 11 | if 12 | ( 13 | !ScrambledBugs.Patterns.Patches.PowerAttackStamina.GetStaminaCostActor 14 | || 15 | !ScrambledBugs.Patterns.Patches.PowerAttackStamina.GetStaminaCostPlayerCharacter 16 | || 17 | !ScrambledBugs.Patterns.Patches.PowerAttackStamina.HasStaminaActor 18 | || 19 | !ScrambledBugs.Patterns.Patches.PowerAttackStamina.HasStaminaCostActor 20 | || 21 | !ScrambledBugs.Patterns.Patches.PowerAttackStamina.HasStaminaCostPlayerCharacter 22 | || 23 | !ScrambledBugs.Patterns.Patches.PowerAttackStamina.HasStaminaPlayerCharacter 24 | ) 25 | { 26 | return false; 27 | } 28 | 29 | Memory.SafeFill(ScrambledBugs.Offsets.Patches.PowerAttackStamina.HasStaminaActor, 2, Assembly.Nop); 30 | Memory.SafeFill(ScrambledBugs.Offsets.Patches.PowerAttackStamina.HasStaminaPlayerCharacter, 2, Assembly.Nop); 31 | 32 | PowerAttackStamina.CanPowerAttack(); 33 | 34 | return true; 35 | } 36 | 37 | 38 | 39 | static public void CanPowerAttack() 40 | { 41 | Trampoline.WriteRelativeCallBranch 42 | ( 43 | ScrambledBugs.Offsets.Patches.PowerAttackStamina.GetStaminaCostActor, 44 | PowerAttackStamina.CanPowerAttack(Memory.ReadRelativeCall(ScrambledBugs.Offsets.Patches.PowerAttackStamina.GetStaminaCostActor)) 45 | ); 46 | 47 | var assemblyActor = new UnmanagedArray(); 48 | 49 | assemblyActor.Add(new System.Byte[2] { 0x84, 0xC0 }); // test al, al 50 | assemblyActor.Add(new System.Byte[1] { Assembly.Nop }); // nop 51 | assemblyActor.Add(new System.Byte[2] { 0x74, 0x6E }); // jz 6E 52 | 53 | Memory.SafeWrite(ScrambledBugs.Offsets.Patches.PowerAttackStamina.HasStaminaCostActor, assemblyActor); 54 | 55 | 56 | 57 | Trampoline.WriteRelativeCallBranch 58 | ( 59 | ScrambledBugs.Offsets.Patches.PowerAttackStamina.GetStaminaCostPlayerCharacter, 60 | PowerAttackStamina.CanPowerAttack(Memory.ReadRelativeCall(ScrambledBugs.Offsets.Patches.PowerAttackStamina.GetStaminaCostPlayerCharacter)) 61 | ); 62 | 63 | var assemblyPlayerCharacter = new UnmanagedArray(); 64 | 65 | assemblyPlayerCharacter.Add(new System.Byte[2] { 0x84, 0xC0 }); // test al, al 66 | assemblyPlayerCharacter.Add(new System.Byte[1] { Assembly.Nop }); // nop 67 | assemblyPlayerCharacter.Add(new System.Byte[2] { 0x75, 0x34 }); // jnz 34 68 | 69 | Memory.SafeWrite(ScrambledBugs.Offsets.Patches.PowerAttackStamina.HasStaminaCostPlayerCharacter, assemblyPlayerCharacter); 70 | } 71 | 72 | 73 | 74 | static public System.Byte[] CanPowerAttack(void* getStaminaCost) 75 | { 76 | var assembly = new UnmanagedArray(); 77 | 78 | assembly.Add(new System.Byte[1] { 0x51 }); // push rcx 79 | assembly.Add(new System.Byte[4] { 0x48, 0x83, 0xEC, 0x20 }); // sub rsp, 20 80 | assembly.Add(Assembly.AbsoluteCall(getStaminaCost)); // call ActorValueOwner.GetStaminaCost 81 | 82 | assembly.Add(new System.Byte[3] { 0x0F, 0x57, 0xC9 }); // xorps xmm1, xmm1 83 | assembly.Add(new System.Byte[3] { 0x0F, 0x2F, 0xC1 }); // comiss xmm0, xmm1 84 | assembly.Add(new System.Byte[2] { 0x76, (5 + 5 + 3 + 6 + 3) + (5 + 2) + (2 + 2) }); // jbe 21 85 | 86 | assembly.Add(new System.Byte[5] { 0xBA, 0x1A, 0x00, 0x00, 0x00 }); // mov edx, 1A 87 | assembly.Add(new System.Byte[5] { 0x48, 0x8B, 0x4C, 0x24, 0x20 }); // mov rcx, [rsp+20] 88 | assembly.Add(new System.Byte[3] { 0x48, 0x8B, 0x01 }); // mov rax, [rcx] 89 | assembly.Add(new System.Byte[6] { 0xF3, 0x0F, 0x11, 0x44, 0x24, 0x20 }); // movss [rsp+20], xmm0 90 | assembly.Add(new System.Byte[3] { 0xFF, 0x50, 0x08 }); // call [rax+8] (ActorValueOwner.GetActorValue) 91 | 92 | assembly.Add(new System.Byte[5] { 0x0F, 0x2F, 0x44, 0x24, 0x20 }); // comiss xmm0, [rsp+20] 93 | assembly.Add(new System.Byte[2] { 0x73, 2 + 2 }); // jae 4 94 | 95 | assembly.Add(new System.Byte[2] { 0x31, 0xC0 }); // xor eax, eax 96 | assembly.Add(new System.Byte[2] { 0xEB, 0x05 }); // jmp 5 97 | 98 | assembly.Add(new System.Byte[5] { 0xB8, 0x01, 0x00, 0x00, 0x00 }); // mov eax, 1 99 | 100 | assembly.Add(new System.Byte[4] { 0x48, 0x83, 0xC4, 0x28 }); // add rsp, 28 101 | assembly.Add(new System.Byte[1] { Assembly.Ret }); // ret 102 | 103 | return assembly; 104 | 105 | /* 106 | ActorValueOwner* actorValueOwner; // rcx 107 | BGSAttackData* attackData; // rdx 108 | 109 | var staminaCost = actorValueOwner->GetStaminaCost(attackData); 110 | 111 | if (staminaCost <= 0.0F) 112 | { 113 | return true; 114 | } 115 | 116 | var stamina = actorValueOwner->GetActorValue(ActorValue.Stamina); 117 | 118 | if (stamina >= staminaCost) 119 | { 120 | return true; 121 | } 122 | 123 | return false; 124 | */ 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Patches/ReflectDamage.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Patches 6 | { 7 | static internal class ReflectDamage 8 | { 9 | static public System.Boolean Patch() 10 | { 11 | if (!ScrambledBugs.Patterns.Patches.ReflectDamage.CompareReflectDamage) 12 | { 13 | return false; 14 | } 15 | 16 | Memory.SafeFill(ScrambledBugs.Offsets.Patches.ReflectDamage.CompareReflectDamage, 2, Assembly.Nop); 17 | 18 | return true; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Patches/TeammateDifficulty.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Patches 6 | { 7 | static internal class TeammateDifficulty 8 | { 9 | static public System.Boolean Patch() 10 | { 11 | if (!ScrambledBugs.Patterns.Patches.TeammateDifficulty.IsPlayer) 12 | { 13 | return false; 14 | } 15 | 16 | TeammateDifficulty.IsPlayerOrTeammate(); 17 | 18 | return true; 19 | } 20 | 21 | 22 | 23 | static public void IsPlayerOrTeammate() 24 | { 25 | var assembly = new UnmanagedArray(); 26 | 27 | assembly.Add(Memory.ReadArray(ScrambledBugs.Offsets.Patches.TeammateDifficulty.IsPlayer, System.Runtime.CompilerServices.Unsafe.SizeOf())); // mov edx, 18 28 | assembly.Add(new System.Byte[2] { 0x74, 6 + 3 + 2 + 2 }); // je B 29 | 30 | assembly.Add(new System.Byte[6] { 0x8B, 0x81, 0xE0, 0x00, 0x00, 0x00 }); // mov eax, [rcx+E0] 31 | assembly.Add(new System.Byte[3] { 0xC1, 0xE8, 0x1A }); // shr eax, 1A 32 | assembly.Add(new System.Byte[2] { 0xF6, 0xD0 }); // not al 33 | assembly.Add(new System.Byte[2] { 0xA8, 0x01 }); // test al, 1 34 | 35 | assembly.Add(new System.Byte[1] { Assembly.Ret }); // ret 36 | 37 | Trampoline.WriteRelativeCallBranch(ScrambledBugs.Offsets.Patches.TeammateDifficulty.IsPlayer, assembly); 38 | 39 | // rax 40 | // eflags 41 | 42 | // actor != null 43 | 44 | /* 45 | Actor* actor; // rcx 46 | 47 | return 48 | (actor == player) 49 | || 50 | ((actor->BoolBits() & ActorBoolBits.PlayerTeammate) == ActorBoolBits.PlayerTeammate); 51 | */ 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Patches/UnderfilledSoulGems.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs.Patches 6 | { 7 | static internal class UnderfilledSoulGems 8 | { 9 | static public System.Boolean Patch() 10 | { 11 | if (!ScrambledBugs.Patterns.Patches.UnderfilledSoulGems.CompareSoulLevelValue) 12 | { 13 | return false; 14 | } 15 | 16 | Memory.SafeWrite(ScrambledBugs.Offsets.Patches.UnderfilledSoulGems.CompareSoulLevelValue, new System.Byte?[2] { 0x75, null }); 17 | 18 | return true; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Plugin.cs: -------------------------------------------------------------------------------- 1 | using Eggstensions; 2 | 3 | 4 | 5 | namespace ScrambledBugs 6 | { 7 | static public class Plugin 8 | { 9 | [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] 10 | static public void Initialize() 11 | { 12 | try 13 | { 14 | var settings = System.Text.Json.JsonSerializer.Deserialize 15 | ( 16 | System.IO.File.ReadAllText(System.IO.Path.Combine(Main.ExecutingAssemblyDirectoryName, $"{Main.ExecutingAssemblyName}.json")), 17 | new System.Text.Json.JsonSerializerOptions() 18 | { 19 | AllowTrailingCommas = true, 20 | PropertyNameCaseInsensitive = true, 21 | ReadCommentHandling = System.Text.Json.JsonCommentHandling.Skip 22 | } 23 | ); 24 | 25 | Log.Information($"Initializing...\n{System.Text.Json.JsonSerializer.Serialize(settings, new System.Text.Json.JsonSerializerOptions() { PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase, WriteIndented = true })}"); 26 | 27 | // Fixes 28 | if (settings?.Fixes?.ActorValuePercentage ?? false) 29 | { 30 | settings.Fixes.ActorValuePercentage = ScrambledBugs.Fixes.ActorValuePercentage.Fix(); 31 | } 32 | 33 | if (settings?.Fixes?.HarvestedFlags ?? false) 34 | { 35 | settings.Fixes.HarvestedFlags = ScrambledBugs.Fixes.HarvestedFlags.Fix(); 36 | } 37 | 38 | if (settings?.Fixes?.HitEffectRaceCondition ?? false) 39 | { 40 | settings.Fixes.HitEffectRaceCondition = ScrambledBugs.Fixes.HitEffectRaceCondition.Fix(); 41 | } 42 | 43 | if (settings?.Fixes?.MagicEffectConditions ?? false) 44 | { 45 | settings.Fixes.MagicEffectConditions = ScrambledBugs.Fixes.MagicEffectConditions.Fix(); 46 | } 47 | 48 | if (settings?.Fixes?.MagicEffectFlags ?? false) 49 | { 50 | settings.Fixes.MagicEffectFlags = ScrambledBugs.Fixes.MagicEffectFlags.Fix(); 51 | } 52 | 53 | if (settings?.Fixes?.ModArmorWeightPerkEntryPoint ?? false) 54 | { 55 | settings.Fixes.ModArmorWeightPerkEntryPoint = ScrambledBugs.Fixes.ModArmorWeightPerkEntryPoint.Fix(); 56 | } 57 | 58 | if ((settings?.Fixes?.QuickShot ?? false) && (settings?.Fixes?.QuickShotPlaybackSpeed.HasValue ?? false)) 59 | { 60 | settings.Fixes.QuickShot = ScrambledBugs.Fixes.QuickShot.Fix(settings.Fixes.QuickShotPlaybackSpeed.Value); 61 | } 62 | 63 | if (settings?.Fixes?.SpeedMultUpdates ?? false) 64 | { 65 | settings.Fixes.SpeedMultUpdates = ScrambledBugs.Fixes.SpeedMultUpdates.Fix(); 66 | } 67 | 68 | if (settings?.Fixes?.TerrainDecals ?? false) 69 | { 70 | settings.Fixes.TerrainDecals = ScrambledBugs.Fixes.TerrainDecals.Fix(); 71 | } 72 | 73 | if (settings?.Fixes?.TrainingMenuText ?? false) 74 | { 75 | settings.Fixes.TrainingMenuText = ScrambledBugs.Fixes.TrainingMenuText.Fix(); 76 | } 77 | 78 | if (settings?.Fixes?.WeaponCharge ?? false) 79 | { 80 | settings.Fixes.WeaponCharge = ScrambledBugs.Fixes.WeaponCharge.Fix(); 81 | } 82 | 83 | // Patches 84 | if (settings?.Patches?.AccumulatingMagnitude ?? false) 85 | { 86 | settings.Patches.AccumulatingMagnitude = ScrambledBugs.Patches.AccumulatingMagnitude.Patch(); 87 | } 88 | 89 | if (settings?.Patches?.AlreadyCaughtPickpocketing ?? false) 90 | { 91 | settings.Patches.AlreadyCaughtPickpocketing = ScrambledBugs.Patches.AlreadyCaughtPickpocketing.Patch(); 92 | } 93 | 94 | if (settings?.Patches?.ApplySpellPerkEntryPoints?.MultipleSpells ?? false) 95 | { 96 | settings.Patches.ApplySpellPerkEntryPoints.MultipleSpells = ScrambledBugs.Patches.ApplySpellPerkEntryPoints.MultipleSpells.Patch(settings?.Patches?.ApplySpellPerkEntryPoints?.CastSpells ?? false); 97 | } 98 | else if (settings?.Patches?.ApplySpellPerkEntryPoints?.CastSpells ?? false) 99 | { 100 | settings.Patches.ApplySpellPerkEntryPoints.CastSpells = ScrambledBugs.Patches.ApplySpellPerkEntryPoints.CastSpells.Patch(); 101 | } 102 | 103 | if (settings?.Patches?.AttachHitEffectArt ?? false) 104 | { 105 | settings.Patches.AttachHitEffectArt = ScrambledBugs.Patches.AttachHitEffectArt.Patch(); 106 | } 107 | 108 | if (settings?.Patches?.EquipBestAmmo ?? false) 109 | { 110 | settings.Patches.EquipBestAmmo = ScrambledBugs.Patches.EquipBestAmmo.Patch(); 111 | } 112 | 113 | if (settings?.Patches?.LeveledCharacters ?? false) 114 | { 115 | settings.Patches.LeveledCharacters = ScrambledBugs.Patches.LeveledCharacters.Patch(); 116 | } 117 | 118 | if (settings?.Patches?.LockpickingExperience ?? false) 119 | { 120 | settings.Patches.LockpickingExperience = ScrambledBugs.Patches.LockpickingExperience.Patch(); 121 | } 122 | 123 | if (settings?.Patches?.MultipleHitEffects ?? false) 124 | { 125 | settings.Patches.MultipleHitEffects = ScrambledBugs.Patches.MultipleHitEffects.Patch(); 126 | } 127 | 128 | if (settings?.Patches?.PausedGameHitEffects ?? false) 129 | { 130 | settings.Patches.PausedGameHitEffects = ScrambledBugs.Patches.PausedGameHitEffects.Patch(); 131 | } 132 | 133 | if (settings?.Patches?.PowerAttackStamina ?? false) 134 | { 135 | settings.Patches.PowerAttackStamina = ScrambledBugs.Patches.PowerAttackStamina.Patch(); 136 | } 137 | 138 | if (settings?.Patches?.ReflectDamage ?? false) 139 | { 140 | settings.Patches.ReflectDamage = ScrambledBugs.Patches.ReflectDamage.Patch(); 141 | } 142 | 143 | if (settings?.Patches?.TeammateDifficulty ?? false) 144 | { 145 | settings.Patches.TeammateDifficulty = ScrambledBugs.Patches.TeammateDifficulty.Patch(); 146 | } 147 | 148 | if (settings?.Patches?.UnderfilledSoulGems ?? false) 149 | { 150 | settings.Patches.UnderfilledSoulGems = ScrambledBugs.Patches.UnderfilledSoulGems.Patch(); 151 | } 152 | 153 | // Fixes 154 | if (settings?.Fixes?.ApplySpellPerkEntryPoints?.Arrows ?? false) 155 | { 156 | settings.Fixes.ApplySpellPerkEntryPoints.Arrows = ScrambledBugs.Fixes.ApplySpellPerkEntryPoints.Arrows.Fix(); 157 | } 158 | 159 | Trampoline.Commit(); 160 | 161 | Log.Information($"Initialized.\n{System.Text.Json.JsonSerializer.Serialize(settings, new System.Text.Json.JsonSerializerOptions() { PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase, WriteIndented = true })}"); 162 | } 163 | catch (System.Exception exception) // System.IO.FileNotFoundException, System.Text.Json.JsonException 164 | { 165 | Log.Information($"{exception}"); 166 | 167 | throw; 168 | } 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/ScrambledBugs.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | true 6 | 7 | 8 | 9 | x64 10 | true 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /ScrambledBugs/ScrambledBugs/Settings.cs: -------------------------------------------------------------------------------- 1 | namespace ScrambledBugs 2 | { 3 | public class JsonSettings 4 | { 5 | public class JsonFixes 6 | { 7 | public class JsonApplySpellPerkEntryPoints 8 | { 9 | public System.Boolean? Arrows { get; set; } 10 | } 11 | 12 | 13 | 14 | public System.Boolean? ActorValuePercentage { get; set; } 15 | public JsonFixes.JsonApplySpellPerkEntryPoints ApplySpellPerkEntryPoints { get; set; } 16 | public System.Boolean? HarvestedFlags { get; set; } 17 | public System.Boolean? HitEffectRaceCondition { get; set; } 18 | public System.Boolean? MagicEffectConditions { get; set; } 19 | public System.Boolean? MagicEffectFlags { get; set; } 20 | public System.Boolean? ModArmorWeightPerkEntryPoint { get; set; } 21 | public System.Boolean? QuickShot { get; set; } 22 | public System.Single? QuickShotPlaybackSpeed { get; set; } 23 | public System.Boolean? SpeedMultUpdates { get; set; } 24 | public System.Boolean? TerrainDecals { get; set; } 25 | public System.Boolean? TrainingMenuText { get; set; } 26 | public System.Boolean? WeaponCharge { get; set; } 27 | } 28 | 29 | public class JsonPatches 30 | { 31 | public class JsonApplySpellPerkEntryPoints 32 | { 33 | public System.Boolean? CastSpells { get; set; } 34 | public System.Boolean? MultipleSpells { get; set; } 35 | } 36 | 37 | 38 | 39 | public System.Boolean? AccumulatingMagnitude { get; set; } 40 | public System.Boolean? AlreadyCaughtPickpocketing { get; set; } 41 | public JsonPatches.JsonApplySpellPerkEntryPoints ApplySpellPerkEntryPoints { get; set; } 42 | public System.Boolean? AttachHitEffectArt { get; set; } 43 | public System.Boolean? EquipBestAmmo { get; set; } 44 | public System.Boolean? LeveledCharacters { get; set; } 45 | public System.Boolean? LockpickingExperience { get; set; } 46 | public System.Boolean? MultipleHitEffects { get; set; } 47 | public System.Boolean? PausedGameHitEffects { get; set; } 48 | public System.Boolean? PowerAttackStamina { get; set; } 49 | public System.Boolean? ReflectDamage { get; set; } 50 | public System.Boolean? TeammateDifficulty { get; set; } 51 | public System.Boolean? UnderfilledSoulGems { get; set; } 52 | } 53 | 54 | 55 | 56 | public JsonSettings.JsonFixes Fixes { get; set; } 57 | public JsonSettings.JsonPatches Patches { get; set; } 58 | } 59 | } 60 | --------------------------------------------------------------------------------