{"id":1096,"date":"2021-01-17T07:00:56","date_gmt":"2021-01-17T12:00:56","guid":{"rendered":"https:\/\/badecho.com\/?p=1096"},"modified":"2021-01-20T13:27:37","modified_gmt":"2021-01-20T18:27:37","slug":"hacking-ac-valhalla-part-7","status":"publish","type":"post","link":"https:\/\/badecho.com\/index.php\/2021\/01\/17\/hacking-ac-valhalla-part-7\/","title":{"rendered":"Hacking Assassin&#8217;s Creed: Valhalla &#8211; Part 7 (Post-Debut Fixes)"},"content":{"rendered":"\n<h2>A Few Middling Concerns Remain<\/h2>\n\n\n\n<p>The playthrough of <a href=\"https:\/\/badecho.com\/index.php\/what-is-omnified\/\" target=\"_blank\" rel=\"noreferrer noopener\">Omnified<\/a> <em>Assassin&#8217;s Creed: Valhalla<\/em> live on <a href=\"https:\/\/twitch.tv\/omni\" target=\"_blank\" rel=\"noreferrer noopener\">stream<\/a> has been a most joyous affair. I can already tell that the Omnification of the game is going to cause the playtime required to beat it to balloon in size. It&#8217;s going to be quite a long time still until we can consider it beaten and dead.<\/p>\n\n\n\n<p>That being said, given that we have so much playtime of the game remaining, I want to be sure that as much of that time is spent enjoying the playthrough as opposed to worrying over it. I definitely have my set of strange quirks that set me off, and when certain things go wrong or don&#8217;t work right with the changes I&#8217;ve made to a game, they are liable to make me upset.<\/p>\n\n\n\n<p>While this has been the most stable and bug-free Omnified game yet, there exist a few problems causing a bit of consternation with me, and I need them corrected before I can continue this playthrough in peace. Here&#8217;s a list of what&#8217;s bugging me:<\/p>\n\n\n\n<ol><li>No support for player Abomnification.<\/li><li>At a medium distance, NPCs begin to periodically lose their Abomnified scales, causing them to revert to their normal size briefly. This causes a bit of a janky, jittering shape-changing effect to be observed. This is my main &#8220;pain point&#8221;.<\/li><li>During kill animations, where the player is killing an enemy, the Apocalypse system is somehow being triggered as if the player is the one receiving the damage.<\/li><\/ol>\n\n\n\n<p>So, instead of fretting about any of these things anymore, let&#8217;s get to fixing the problems my friends.<\/p>\n\n\n\n<h2>Adding Support for Player Abomnification<\/h2>\n\n\n\n<p>The reason why no toggleable option exists to enable player Abomnification (where the player&#8217;s shape begins changing randomly like other NPCs) is because the coordinate polling function where the Abomnification initiation point is inserted into only polls for NPC coordinates, never the player&#8217;s. So, we just need to find a polling function that only accesses the player&#8217;s coordinates at a similar frequency to the other polling function we&#8217;re using for NPCs.<\/p>\n\n\n\n<p>Right clicking on the player&#8217;s coordinates and looking for code accessing it, we get the following:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"946\" height=\"533\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/PlayerAbomnificationPoints.png\" alt=\"Shows code accessing our player's coordinates, with the highlighted instruction being one of interest.\" class=\"wp-image-1100\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/PlayerAbomnificationPoints.png 946w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/PlayerAbomnificationPoints-300x169.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/PlayerAbomnificationPoints-768x433.png 768w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/PlayerAbomnificationPoints-480x270.png 480w\" sizes=\"(max-width: 946px) 100vw, 946px\" \/><figcaption>The highlighted instruction isn&#8217;t executing a ton, but it&#8217;s using the proper offset.<\/figcaption><\/figure><\/div>\n\n\n\n<p>There are so many instructions accessing our player&#8217;s coordinates. It&#8217;s good to know that we have lots of viable candidates at our disposal. For our convenience, however, I&#8217;ve decided to choose one that is accessing our player&#8217;s coordinates at an offset of <code>0x50<\/code>, which means I don&#8217;t have to adjust the address at all to match it up with the known player coordinate pointer. <\/p>\n\n\n\n<p>The highlighted instruction viewable in the image above is where I&#8217;m going to inject another Abomnification initiation point into.<\/p>\n\n\n\n<h3>Player Abomnification Initiation Hook<\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Initiates the Abomnification system for the player.\n\/\/ UNIQUE AOB: 0F 57 C9 0F 10 73 50\ndefine(omnifyPlayerAbomnificationHook, &quot;ACValhalla.exe&quot; + 16590FD)\n\nassert(omnifyPlayerAbomnificationHook, 0F 57 C9 0F 10 73 50)\nalloc(initiatePlayerAbomnification,$1000, omnifyPlayerAbomnificationHook)\n\nregistersymbol(omnifyPlayerAbomnificationHook)\n\ninitiatePlayerAbomnification:\n  pushf\n  \/\/ Back up the registers used to hold return values.\n  push rax\n  push rbx\n  push rcx\n  \/\/ Push the identifying address parameter and call the Abomnification system.\n  push rbx\n  call executeAbomnification\n  \/\/ Restore the preserved values on the stack.\n  pop rcx\n  pop rbx\n  pop rax\ninitiatePlayerAbomnificationOriginalCode:\n  popf\n  xorps xmm1,xmm1\n  movups xmm6,[rbx+50]\n  jmp initiatePlayerAbomnificationReturn\n\n\nomnifyPlayerAbomnificationHook:\n  jmp initiatePlayerAbomnification\n  nop 2\ninitiatePlayerAbomnificationReturn:\n<\/pre>\n\n\n<p>With scale generation now implemented for the player, we just need to add a toggle option in the scale application hook in order to allow for the player to become Abomnified.<\/p>\n\n\n\n<h3>Updated Abomnification Scale Application Hook<\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Applies Abomnification generated scale multipliers.\n\/\/ Unique AOB: 0F 11 62 10 4C 03 C1\ndefine(omnifyApplyAbomnificationHook, &quot;ACValhalla.exe&quot; + E8F813)\n\nassert(omnifyApplyAbomnificationHook, 44 0F 59 05 55 DC 2E 03)\nalloc(applyAbomnification,$1000, omnifyApplyAbomnificationHook)\nalloc(abomnifyPlayer,8)\n\nregistersymbol(omnifyApplyAbomnificationHook)\nregistersymbol(abomnifyPlayer)\n\napplyAbomnification:\n  pushf\n  \/\/ Ensure that the player location struct has been initialized.\n  push rax\n  mov rax,playerLocation\n  cmp [rax],0\n  pop rax\n  je applyAbomnificationOriginalCode\n  \/\/ Backing up an SSE register to hold our multiplier.\n  sub rsp,10\n  movdqu [rsp],xmm0  \n  \/\/ Backing up the registers used to hold return values by the\n  \/\/ Abomnification system.\n  push rax\n  push rbx\n  push rcx  \n  \/\/ A rendering supplementary data structure is stored on the stack.\n  mov rax,[rsp+6A]\n  \/\/ If the bytes at 0x14 are not zeroed, then the rendering data structure\n  \/\/ is not pointing to a location structure.\n  mov rbx,[rax+14]\n  cmp ebx,0\n  jne applyAbomnificationExit\n  \/\/ The location structure is found here, however we need to check that \n  \/\/ it's a valid pointer, as there is still a chance for some junk data here.\n  mov rbx,[rax+18]  \n  push rcx\n  lea rcx,[rbx]\n  call checkBadPointer\n  cmp ecx,0\n  pop rcx\n  jne applyAbomnificationExit    \n  cmp [abomnifyPlayer],1\n  je continueAbomnification\n  \/\/ Ensure that the player isn't going to be Abomnified.\n  mov rax,playerLocation\n  cmp rbx,[rax]\n  je applyAbomnificationExit\ncontinueAbomnification:\n  \/\/ Push the identifying address parameter and get the Abomnified scales.  \n  push rbx\n  call getAbomnifiedScales\n  \/\/ Make some room on the stack so we can construct the multiplier SSE register.\n  sub rsp,10\n  movss xmm0,[identityValue]\n  shufps xmm0,xmm0,0\n  movups [rsp],xmm0\n  mov [rsp],eax\n  mov [rsp+4],ecx\n  mov [rsp+8],ebx\n  movups xmm0,[rsp]\n  add rsp,10\n  \/\/ Apply the Abomnified scale multipliers to the register that will be applied\n  \/\/ against the global scale parameters.\n  mulps xmm8,xmm0\napplyAbomnificationExit:\n  \/\/ Restore the preserved values on the stack.\n  pop rcx\n  pop rbx\n  pop rax\n  movdqu xmm0,[rsp]\n  add rsp,10\napplyAbomnificationOriginalCode:\n  popf \n  mulps xmm8,[ACValhalla.exe+417D470]\n  jmp applyAbomnificationReturn\n\n\nomnifyApplyAbomnificationHook:\n  jmp applyAbomnification\n  nop 3\napplyAbomnificationReturn:\n\n\nabomnifyPlayer:\n  dd 0\n<\/pre>\n\n\n<p>And voila! We now have an Abomnifiable player:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"1015\" height=\"613\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/FatPlayer.png\" alt=\"Shows the player Abomnified and fat.\" class=\"wp-image-1101\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/FatPlayer.png 1015w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/FatPlayer-300x181.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/FatPlayer-768x464.png 768w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/FatPlayer-480x290.png 480w\" sizes=\"(max-width: 1015px) 100vw, 1015px\" \/><figcaption>The player is looking nice, Abomnified, and fat.<\/figcaption><\/figure><\/div>\n\n\n\n<p>Wish it wasn&#8217;t always dark in my game. And of course, as I&#8217;m typing this, the setting sun is now shining on my character, but too late! Already took the picture.<\/p>\n\n\n\n<p>Now that the player is Abomnified, perhaps it&#8217;ll make this next&#8230;much more difficult issue easier to solve.<\/p>\n\n\n\n<h2>Fixing the Periodic Loss of Abomnified Scales<\/h2>\n\n\n\n<p>This is one that has been bugging me for a bit, but I didn&#8217;t want to draw attention to it on stream, for fear of people being able to see the problem when they otherwise might&#8217;ve not even noticed. So I&#8217;ve been suffering with it, <em>silently<\/em>. <\/p>\n\n\n\n<p>When NPCs are a certain distance from the player, they will begin to lose their Abomnified scales, reverting back to their normal size, but only briefly. Then, after a brief period of time, they will go back to their Abomnified scales. All of this will then repeat. This results in a sort of &#8220;stuttering&#8221; back and forth between unnatural size and natural size.<\/p>\n\n\n\n<p>I knew of this potentially being a problem when I initially implemented the Abomnification system, however any change relating to custom scaling code needs to be evaluated using a cost-benefit analysis approach. I have lots of other things that needs doing, so unless something is <em>desperately<\/em> needed, it makes sense to try to make do with what we got as far as custom scaling stuff goes.<\/p>\n\n\n\n<p>Anyway, clearly some secondary rendering function is taking over, causing our hook to essentially become superseded. There are many, many functions in the game that do the math responsible for laying out the character model polygonal mesh. I even tried finding some new ones to hook into, in order to take care of this particular problem.<\/p>\n\n\n\n<p>That was just going to end up taking too much time. Instead of all that, I stopped myself, took another look at the problem, and decided to attack it a different way. The scales were most often starting to drop off once NPCs were at a certain distance from the player. Why not then add in some functionality that would only allow for Abomnified scales to be applied if NPCs were within a particular radius?<\/p>\n\n\n\n<p>We already have the functionality required for determining coordinate distances with the Predator system&#8217;s <code>getCoordinateDistance<\/code> function. So, I simply made a few additions to the Abomnification scale application hook in order to incorporate a new <code>abomnificationRadius<\/code> floating point symbol.<\/p>\n\n\n\n<h3>Updated Abomnification Scale Application Hook<\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Applies Abomnification generated scale multipliers.\n\/\/ Unique AOB: 0F 11 62 10 4C 03 C1\ndefine(omnifyApplyAbomnificationHook, &quot;ACValhalla.exe&quot; + E8F813)\n\nassert(omnifyApplyAbomnificationHook, 44 0F 59 05 55 DC 2E 03)\nalloc(applyAbomnification,$1000, omnifyApplyAbomnificationHook)\nalloc(abomnifyPlayer,8)\nalloc(abomnificationRadius,8)\n\nregistersymbol(omnifyApplyAbomnificationHook)\nregistersymbol(abomnifyPlayer)\nregistersymbol(abomnificationRadius)\n\napplyAbomnification:\n  pushf\n  \/\/ Ensure that the player location struct has been initialized.\n  push rax\n  mov rax,playerLocation\n  cmp [rax],0\n  pop rax\n  je applyAbomnificationOriginalCode\n  \/\/ Backing up an SSE register to hold our multiplier.\n  sub rsp,10\n  movdqu [rsp],xmm0  \n  \/\/ Backing up the registers used to hold return values by the\n  \/\/ Abomnification system.\n  push rax\n  push rbx\n  push rcx  \n  \/\/ A rendering supplementary data structure is stored on the stack.\n  mov rax,[rsp+6A]\n  \/\/ If the bytes at 0x14 are not zeroed, then the rendering data structure\n  \/\/ is not pointing to a location structure.\n  mov rbx,[rax+14]\n  cmp ebx,0\n  jne applyAbomnificationExit\n  \/\/ The location structure is found here, however we need to check that \n  \/\/ it's a valid pointer, as there is still a chance for some junk data here.\n  mov rbx,[rax+18]  \n  push rcx\n  lea rcx,[rbx+50]\n  call checkBadPointer\n  cmp ecx,0\n  pop rcx\n  jne applyAbomnificationExit    \n  cmp [abomnifyPlayer],1\n  je continueAbomnification\n  \/\/ Ensure that the player isn't going to be Abomnified.\n  mov rax,playerLocation\n  cmp rbx,[rax]\n  je applyAbomnificationExit\ncontinueAbomnification:\n  \/\/ Push the player's and rendering target's coordinates to the stack\n  \/\/ and then calculate the distance between them.\n  mov rax,playerLocation\n  mov rcx,[rax]\n  push [rcx+50]\n  push [rcx+58]\n  push [rbx+50]\n  push [rbx+58]  \n  call findCoordinateDistance\n  \/\/ If the rendering target isn't within the radius, we abort Abomnification.\n  movd xmm0,eax\n  ucomiss xmm0,[abomnificationRadius]\n  ja applyAbomnificationExit\n  \/\/ Push the identifying address parameter and get the Abomnified scales.  \n  push rbx\n  call getAbomnifiedScales\n  \/\/ Make some room on the stack so we can construct the multiplier SSE register.\n  sub rsp,10\n  movss xmm0,[identityValue]\n  shufps xmm0,xmm0,0\n  movups [rsp],xmm0\n  mov [rsp],eax\n  mov [rsp+4],ecx\n  mov [rsp+8],ebx\n  movups xmm0,[rsp]\n  add rsp,10\n  \/\/ Apply the Abomnified scale multipliers to the register that will be applied\n  \/\/ against the global scale parameters.\n  mulps xmm8,xmm0\napplyAbomnificationExit:\n  \/\/ Restore the preserved values on the stack.\n  pop rcx\n  pop rbx\n  pop rax\n  movdqu xmm0,[rsp]\n  add rsp,10\napplyAbomnificationOriginalCode:\n  popf \n  mulps xmm8,[ACValhalla.exe+417D470]\n  jmp applyAbomnificationReturn\n\n\nomnifyApplyAbomnificationHook:\n  jmp applyAbomnification\n  nop 3\napplyAbomnificationReturn:\n\n\nabomnifyPlayer:\n  dd 0\n  \nabomnificationRadius:\n  dd (float)30.0\n<\/pre>\n\n\n<p>Initially we will be rocking a radius of <code>30.0<\/code>, as this seemed to be around where the NPCs started glitching out. After trying out the above code for a bit, I can say that things appear to be much, much better! This is a good workaround for this particular issue &#8212; any solution more complete than this just isn&#8217;t going to be worth the time investment for me.<\/p>\n\n\n\n<p>The radius might need tweaking, we&#8217;ll have to do some serious play to find out. If I do change it at all, you&#8217;ll be able to see the final value when I post the tombstone for this game.<\/p>\n\n\n\n<h2>Player Kill Animations Killing&#8230;The Player<\/h2>\n\n\n\n<p>This is a bit of a strange one, although its strangeness is dwarfed by how irritating it was to deal with! When fighting only a very specific type of enemy, I noticed the Player Apocalypse was being triggered during kill animations where the enemy was getting its head smashed. Interestingly, the damage wouldn&#8217;t carry over to the player&#8217;s health, however any effect unrelated to damage (such as teleportitis) would still occur.<\/p>\n\n\n\n<p>So, enemy would be on ground, we go up to enemy and stomp on their head. Then, for whatever reason, a Player Apocalypse roll goes off, lands on teleportitis, launching us up into the air. We then fall down, and die. Right as the enemy&#8217;s head is exploding. A very strange affair indeed.<\/p>\n\n\n\n<p>Naturally, if kill animations (against an enemy) were triggering the Player Apocalypse in general, I&#8217;d definitely would have found that during the Apocalypse implementation. Or at least sometime not long afterwards. But no, it&#8217;s only for a very, <em>very<\/em> specific type of enemy. I have no idea what the name of the enemy is, but they look like this:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"417\" height=\"390\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/FakeDamageSuspects.png\" alt=\"Shows two shady characters who, when performing a kill animation on, cause the Apocalypse system to think that the player is the one being damaged.\" class=\"wp-image-1102\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/FakeDamageSuspects.png 417w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/FakeDamageSuspects-300x281.png 300w\" sizes=\"(max-width: 417px) 100vw, 417px\" \/><figcaption>Look at these two shady characters.<\/figcaption><\/figure><\/div>\n\n\n\n<p>They have these sticks, they throw dust at you, and they&#8217;re kind of annoying. The specific move in which the Player Apocalypse was getting triggered looks like this:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"1024\" height=\"763\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/SquashingHead-1024x763.png\" alt=\"Shows the player character about to smash an enemy's head.\" class=\"wp-image-1104\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/SquashingHead-1024x763.png 1024w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/SquashingHead-300x224.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/SquashingHead-768x572.png 768w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/SquashingHead-480x358.png 480w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/SquashingHead.png 1449w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>We&#8217;re clearly about to smash the enemy&#8217;s head, but we get a Player Apocalypse instead!<\/figcaption><\/figure><\/div>\n\n\n\n<p>It&#8217;s a bit hard to make out from above, but the player is standing over the enemy, ready to squash their head. And of course, once that occurs, an entry is entered into the Apocalypse event log, saying we got 69x&#8217;d, or double damaged, but with no change actually happening on our player&#8217;s health. Incredibly annoying!<\/p>\n\n\n\n<p>So, I put a breakpoint into where the Apocalypse initiation point is inserted, and after triggering it, a very strange picture was painted indeed. It truly, <em>truly<\/em> appeared as if the game was calling this function of code (the damage application code, where damage is about to be applied to a creature&#8217;s health) as if it was indeed the player being damaged.<\/p>\n\n\n\n<p>The current health being worked upon was the player&#8217;s health, not the enemy&#8217;s. The location structure loaded into the <code>rdi<\/code> register (what we use to identify the target of the damage in this game) is the player&#8217;s, not the enemy&#8217;s. Finally, the damage being done appears proportionate to what one expects to do when squashing a head (around 853 damage).<\/p>\n\n\n\n<p>At the end of the function, the huge damage amount is subtracted from our character&#8217;s health, giving a fat negative value. But, after all of this, nothing actually carries over to our player&#8217;s health. I have no idea why the game is doing this, but it is screwing up our handling of damage. Very annoying.<\/p>\n\n\n\n<p>After trying to find patterns by looking high and low through the available data, I eventually determined (by taking a <code>diff<\/code> between a stack snapshot of me doing the kill animation and normal damage being done to the player) that a value of <code>0x3F800000<\/code> (which is 1.0 in floating point) would be at <code>[rsp+20]<\/code> (this isn&#8217;t its normal location, rather it is where to find it after we do our stack preservation) only during this unique situation.<\/p>\n\n\n\n<p>So, in order to fix this bug, I simply added a check for this value. Initial testing seems to indicate that the Player Apocalypse no longer goes off during the kill animation, and all other actual damage to the player seems to be handled properly.<\/p>\n\n\n\n<h3>Updated Apocalypse Initiation Hook<\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Initiates the Apocalypse system.\n\/\/ Unique AOB: 2B 45 BC 89 44 24 58\ndefine(omnifyApocalypseHook, &quot;ACValhalla.exe&quot; + 2149247)\n\nassert(omnifyApocalypseHook, 2B 45 BC 89 44 24 58)\nalloc(initiateApocalypse,$1000, omnifyApocalypseHook)\n\nregistersymbol(omnifyApocalypseHook)\n\ninitiateApocalypse:\n  pushf\n  \/\/ Backing up a few SSE registers to hold converted floating points.\n  sub rsp,10\n  movdqu [rsp],xmm0\n  sub rsp,10\n  movdqu [rsp],xmm1\n  sub rsp,10\n  movdqu [rsp],xmm2\n  \/\/ Backing up the rbx register as it will be overwritten by\n  \/\/ the Apocalypse register. We don't care about the rax register\n  \/\/ as we'll be changing it anyway.\n  push rbx\n  \/\/ Backing up a working register to aid in value calculations, etc.\n  push rcx\n  \/\/ Let's grab the damage source right now before the stack shifts\n  \/\/ anymore.\n  mov rcx,[rsp+44A]\nskipLocationCheck:\n  \/\/ We'll convert the working health and damage amount to floats.\n  cvtsi2ss xmm0,eax\n  cvtsi2ss xmm1,[rbp-44]\n  \/\/ If the player is the one receiving the damage, then the rdi register\n  \/\/ will point to the player's location structure.\n  mov rbx,playerLocation\n  cmp [rbx],rdi\n  je initiatePlayerApocalypse\n  \/\/ The player is the one damaging the NPC if the player's root structure\n  \/\/ is listed as the damage source.\n  mov rbx,player\n  cmp [rbx],rcx\n  je initiateEnemyApocalypse\n  jmp initiateApocalypseExit\ninitiatePlayerApocalypse:\n  \/\/ During kill animations on some enemies, the game will sometimes call\n  \/\/ this code as if the player is receiving the damage. \n  \/\/ [rsp+20] seems to be set to (float)1.0 when this is the case.\n  mov rcx,[rsp+20]  \n  cmp rcx,0x3F800000\n  je initiateApocalypseExit\n  \/\/ Realign the player's coordinates so it begins at the X coordinate.\n  mov rbx,playerLocation\n  mov rcx,[rbx]\n  lea rax,[rcx+50]\n  \/\/ Convert the player's maximum health to floating point.\n  mov rbx,playerHealth\n  mov rcx,[rbx]  \n  cvtsi2ss xmm2,[rcx+13C]\n  \/\/ Push the damage amount parameter.\n  sub rsp,8\n  movd [rsp],xmm1\n  \/\/ Push the working health value parameter.\n  sub rsp,8\n  movd [rsp],xmm0\n  \/\/ Push the maximum health value parameter.\n  sub rsp,8\n  movd [rsp],xmm2\n  \/\/ Push the aligned coordinates struct parameter.\n  push rax\n  call executePlayerApocalypse\n  jmp initiateApocalypseUpdateDamage\ninitiateEnemyApocalypse:\n  \/\/ Push the damage amount parameter.\n  sub rsp,8\n  movd [rsp],xmm1\n  \/\/ Push the working health value parameter.\n  sub rsp,8\n  movd [rsp],xmm0\n  call executeEnemyApocalypse\ninitiateApocalypseUpdateDamage:\n  \/\/ Convert the updated damage amount to an integer.\n  movd xmm0,eax\n  cvtss2si eax,xmm0\n  mov [rbp-44],eax\n  \/\/ Convert the updated working health value to an integer.\n  movd xmm0,ebx\n  cvtss2si eax,xmm0\ninitiateApocalypseExit:\n  pop rcx\n  pop rbx  \n  movdqu xmm2,[rsp]\n  add rsp,10\n  movdqu xmm1,[rsp]\n  add rsp,10\n  movdqu xmm0,[rsp]\n  add rsp,10\ninitiateApocalypseOriginalCode:\n  popf\n  sub eax,[rbp-44]\n  mov [rsp+58],eax\n  jmp initiateApocalypseReturn\n\nomnifyApocalypseHook:\n  jmp initiateApocalypse\n  nop 2\ninitiateApocalypseReturn:\n\n\nnegativeVerticalDisplacementEnabled:\n  dd 0\n  \nteleportitisDisplacementX:\n  dd (float)5.0\n  \nyIsVertical:\n  dd 0\n  \nextraDamageX:\n  dd (float)2.0\n<\/pre>\n\n\n<p>Also, I discovered we were restoring values backed up on the stack in the wrong order. We were restoring <code>rbx<\/code> prior to restoring <code>rcx<\/code>. Big oops!<\/p>\n\n\n\n<h2>Let the Games Continue!<\/h2>\n\n\n\n<p>Alright. We just took care of these middling concerns. I look forward to more of this awesome Omnified gameplay, and you should look forward to it too! Remember, to catch this or any other Omnified gameplay live, you have to tune into my stream at: <a rel=\"noreferrer noopener\" href=\"https:\/\/twitch.tv\/omni\" target=\"_blank\">https:\/\/twitch.tv\/omni<\/a><\/p>\n\n\n\n<p>Drop on by the Discord server to say hello, or ask any questions if you have any at: <a href=\"https:\/\/discord.gg\/omni\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/discord.gg\/omni<\/a><\/p>\n\n\n\n<p>Take care, and keep it comfy.<\/p>\n\n\n\n<p><em>~Omni<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A Few Middling Concerns Remain The playthrough of Omnified Assassin&#8217;s Creed: Valhalla live on stream has been a most joyous [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[39,9],"tags":[24,22,33],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v14.9 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\r\n<title>Hacking Assassin&#039;s Creed: Valhalla - Part 7 (Post-Debut) - omni&#039;s hackpad<\/title>\r\n<meta name=\"description\" content=\"An overview of changes and fixes made to Omnified Assassin&#039;s Creed: Valhalla midway through the official playthrough on stream.\" \/>\r\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\r\n<link rel=\"canonical\" href=\"https:\/\/badecho.com\/index.php\/2021\/01\/17\/hacking-ac-valhalla-part-7\/\" \/>\r\n<meta property=\"og:locale\" content=\"en_US\" \/>\r\n<meta property=\"og:type\" content=\"article\" \/>\r\n<meta property=\"og:title\" content=\"Hacking Assassin&#039;s Creed: Valhalla - Part 7 (Post-Debut) - omni&#039;s hackpad\" \/>\r\n<meta property=\"og:description\" content=\"An overview of changes and fixes made to Omnified Assassin&#039;s Creed: Valhalla midway through the official playthrough on stream.\" \/>\r\n<meta property=\"og:url\" content=\"https:\/\/badecho.com\/index.php\/2021\/01\/17\/hacking-ac-valhalla-part-7\/\" \/>\r\n<meta property=\"og:site_name\" content=\"omni&#039;s hackpad\" \/>\r\n<meta property=\"article:published_time\" content=\"2021-01-17T12:00:56+00:00\" \/>\r\n<meta property=\"article:modified_time\" content=\"2021-01-20T18:27:37+00:00\" \/>\r\n<meta property=\"og:image\" content=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/PlayerAbomnificationPoints.png\" \/>\r\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\r\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/badecho.com\/#website\",\"url\":\"https:\/\/badecho.com\/\",\"name\":\"omni&#039;s hackpad\",\"description\":\"Game Code Disassembly. Omnified Modification. Madness.\",\"publisher\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/badecho.com\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/01\/17\/hacking-ac-valhalla-part-7\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/PlayerAbomnificationPoints.png\",\"width\":946,\"height\":533,\"caption\":\"The highlighted instruction isn't executing a ton, but it's using the proper offset.\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/01\/17\/hacking-ac-valhalla-part-7\/#webpage\",\"url\":\"https:\/\/badecho.com\/index.php\/2021\/01\/17\/hacking-ac-valhalla-part-7\/\",\"name\":\"Hacking Assassin's Creed: Valhalla - Part 7 (Post-Debut) - omni&#039;s hackpad\",\"isPartOf\":{\"@id\":\"https:\/\/badecho.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/01\/17\/hacking-ac-valhalla-part-7\/#primaryimage\"},\"datePublished\":\"2021-01-17T12:00:56+00:00\",\"dateModified\":\"2021-01-20T18:27:37+00:00\",\"description\":\"An overview of changes and fixes made to Omnified Assassin's Creed: Valhalla midway through the official playthrough on stream.\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/badecho.com\/index.php\/2021\/01\/17\/hacking-ac-valhalla-part-7\/\"]}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/01\/17\/hacking-ac-valhalla-part-7\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/01\/17\/hacking-ac-valhalla-part-7\/#webpage\"},\"author\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"headline\":\"Hacking Assassin&#8217;s Creed: Valhalla &#8211; Part 7 (Post-Debut Fixes)\",\"datePublished\":\"2021-01-17T12:00:56+00:00\",\"dateModified\":\"2021-01-20T18:27:37+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/01\/17\/hacking-ac-valhalla-part-7\/#webpage\"},\"publisher\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"image\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/01\/17\/hacking-ac-valhalla-part-7\/#primaryimage\"},\"keywords\":\"Hacking,Omnifying,Playtest\",\"articleSection\":\"AC: Valhalla,Games\",\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\",\"name\":\"Matt Weber\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/badecho.com\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/7e345ac2708b3a41c7bd70a4a0440d41?s=96&d=mm&r=g\",\"caption\":\"Matt Weber\"},\"logo\":{\"@id\":\"https:\/\/badecho.com\/#personlogo\"}}]}<\/script>\r\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/1096"}],"collection":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/comments?post=1096"}],"version-history":[{"count":7,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/1096\/revisions"}],"predecessor-version":[{"id":1119,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/1096\/revisions\/1119"}],"wp:attachment":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/media?parent=1096"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/categories?post=1096"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/tags?post=1096"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}