{"id":991,"date":"2020-12-31T18:55:05","date_gmt":"2020-12-31T23:55:05","guid":{"rendered":"https:\/\/badecho.com\/?p=991"},"modified":"2021-01-12T20:07:52","modified_gmt":"2021-01-13T01:07:52","slug":"hacking-ac-valhalla-part-5","status":"publish","type":"post","link":"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/","title":{"rendered":"Hacking Assassin&#8217;s Creed: Valhalla &#8211; Part 5 (Playtest Fixes)"},"content":{"rendered":"\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_11 counter-hierarchy counter-decimal ez-toc-grey\">\r\n<div class=\"ez-toc-title-container\">\r\n<p class=\"ez-toc-title\">Table of Contents<\/p>\r\n<span class=\"ez-toc-title-toggle\"><a class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\"><i class=\"ez-toc-glyphicon ez-toc-icon-toggle\"><\/i><\/a><\/span><\/div>\r\n<nav><ul class=\"ez-toc-list ez-toc-list-level-1\"><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Giving_Omnified_AC_Valhalla_Some_Good_Ole_Testin%E2%80%99\" title=\"Giving Omnified AC: Valhalla Some Good Ole Testin&#8217;\">Giving Omnified AC: Valhalla Some Good Ole Testin&#8217;<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Living_That_Toddler_Viking_Life\" title=\"Living That Toddler Viking Life\">Living That Toddler Viking Life<\/a><ul class=\"ez-toc-list-level-3\"><li class=\"ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Dancing_People_Morphed,_but_Not_Morphing\" title=\"Dancing People Morphed, but Not Morphing\">Dancing People Morphed, but Not Morphing<\/a><ul class=\"ez-toc-list-level-4\"><li class=\"ez-toc-heading-level-4\"><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Updated_Abomnification_Initiation_Point_Hook\" title=\"Updated Abomnification Initiation Point Hook\">Updated Abomnification Initiation Point Hook<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#More_Tiny_Dancing_People_Issues\" title=\"More Tiny Dancing People Issues\">More Tiny Dancing People Issues<\/a><ul class=\"ez-toc-list-level-4\"><li class=\"ez-toc-heading-level-4\"><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Final_()_Abomnification_Initiation_Point_Hook\" title=\"Final (?) Abomnification Initiation Point Hook\">Final (?) Abomnification Initiation Point Hook<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Default_Scales_for_Lookup_Fails\" title=\"Default Scales for Lookup Fails\">Default Scales for Lookup Fails<\/a><ul class=\"ez-toc-list-level-4\"><li class=\"ez-toc-heading-level-4\"><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#getAbomnifiedScales_Unregistered_Morphing_Scale_Data_Update\" title=\"getAbomnifiedScales Unregistered Morphing Scale Data Update\">getAbomnifiedScales Unregistered Morphing Scale Data Update<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Smallified_Is_Too_Small\" title=\"Smallified Is Too Small\">Smallified Is Too Small<\/a><ul class=\"ez-toc-list-level-4\"><li class=\"ez-toc-heading-level-4\"><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Updated_Abomnification_External_Parameters\" title=\"Updated Abomnification External Parameters\">Updated Abomnification External Parameters<\/a><\/li><\/ul><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Grown_Up_Viking_Man\" title=\"Grown Up Viking Man\">Grown Up Viking Man<\/a><ul class=\"ez-toc-list-level-3\"><li class=\"ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Tuning_the_Damage\" title=\"Tuning the Damage\">Tuning the Damage<\/a><ul class=\"ez-toc-list-level-4\"><li class=\"ez-toc-heading-level-4\"><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Updated_Apocalypse_External_Parameters\" title=\"Updated Apocalypse External Parameters\">Updated Apocalypse External Parameters<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Fake_Tom_Petty_Teleportitis_Glitchin%E2%80%99\" title=\"Fake Tom Petty: Teleportitis Glitchin&#8217;\">Fake Tom Petty: Teleportitis Glitchin&#8217;<\/a><ul class=\"ez-toc-list-level-4\"><li class=\"ez-toc-heading-level-4\"><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Bypass_Teleportitis_Overwrite_Hook\" title=\"Bypass Teleportitis Overwrite Hook\">Bypass Teleportitis Overwrite Hook<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Double_Dipping_Apocalypse_From_Fall_Damage\" title=\"Double Dipping Apocalypse From Fall Damage\">Double Dipping Apocalypse From Fall Damage<\/a><ul class=\"ez-toc-list-level-4\"><li class=\"ez-toc-heading-level-4\"><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Updated_Apocalypse_Initiation_Point_Hook\" title=\"Updated Apocalypse Initiation Point Hook\">Updated Apocalypse Initiation Point Hook<\/a><\/li><\/ul><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#Playtest_Complete\" title=\"Playtest Complete\">Playtest Complete<\/a><\/li><\/ul><\/nav><\/div>\r\n<h2><span class=\"ez-toc-section\" id=\"Giving_Omnified_AC_Valhalla_Some_Good_Ole_Testin%E2%80%99\"><\/span>Giving Omnified AC: Valhalla Some Good Ole Testin&#8217;<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Before debuting Omnified <em>Assassin&#8217;s Creed: Valhalla<\/em> on my <a href=\"https:\/\/twitch.tv\/omni\" target=\"_blank\" rel=\"noreferrer noopener\">stream<\/a>, we need to subject it to some fairly rigorous testing so that as few bugs pop up as possible. While I wish for my playthroughs of new games to be as blind as possible, I&#8217;ll subject myself to an hour or two of gameplay to make sure I&#8217;m not constantly fixing things on go-live day.<\/p>\n\n\n\n<p>I&#8217;ll be sharing with all of you a record of my observations as they happen. If I encounter something that needs fixing, you will all get to join me through any of the required deep dives through the code, and you&#8217;ll get to see the solutions I come up with.<\/p>\n\n\n\n<p>I hope we don&#8217;t run into too many problems! But, even if we do, I&#8217;ve given myself quite a bit of time to fix any ensuing issues. My intention is to debut the playthrough on January 1st, 2021. <\/p>\n\n\n\n<p>So&#8230;let&#8217;s see if I can do it!<\/p>\n\n\n\n<h2><span class=\"ez-toc-section\" id=\"Living_That_Toddler_Viking_Life\"><\/span>Living That Toddler Viking Life<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>One little sequence in the game I was aware of (due to having to set up the initial save file to work from) occurs at the very start, as we witness our hero attending a feast as a very young boy. <\/p>\n\n\n\n<p>Naturally, this is a situation in which all of the player specific hooks we&#8217;ve built could easily fail. So, it is with some slight trepidation that I start my playtesting from this very spot in the game.<\/p>\n\n\n\n<p>Luckily, the player-specific hooks seemed to all hold (player&#8217;s vitals are being tracked, player isn&#8217;t speed boosted, player isn&#8217;t Abomnified). The same player-specific code is employed for the hero when they&#8217;re a toddler as when they&#8217;re all grown up. This bodes well for overall stability for our player hooks for different situations that might pop up in the game.<\/p>\n\n\n\n<p>That being said, I only had to take a few steps out of the character&#8217;s bedroom to start noticing some things were amiss.<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Dancing_People_Morphed,_but_Not_Morphing\"><\/span>Dancing People Morphed, but Not Morphing<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>In the main feast hall, we&#8217;re treated to a large crowd of drunken Vikings doing some jigs and having a good time. While they were all obviously Abomnified (shape and size was different from default) none of them were actually <em>Abomnifying<\/em> (shape and size was not continuously changing).<\/p>\n\n\n\n<p>This is most likely due to the Abomnification initiation point only executing a single time (or zero times?) for each NPC. Previously, it was our belief that the location in code in which we <a href=\"https:\/\/badecho.com\/index.php\/2020\/12\/27\/hacking-ac-valhalla-part-4\/#Writing_the_Initiation_Point_Code\" target=\"_blank\" rel=\"noreferrer noopener\">hooked our initiation point into<\/a> was a continuously executing coordinate polling function for NPCs, even if they&#8217;re not moving; however, that does not appear to be the case here.<\/p>\n\n\n\n<p>Let&#8217;s open up our NPC polling function and see what addresses it is accessing.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"508\" height=\"440\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/NPCPollingFunctionMissingSome.png\" alt=\"Shows the addresses being accessed by our NPC polling function. It is only accessing 11.\" class=\"wp-image-994\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/NPCPollingFunctionMissingSome.png 508w, https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/NPCPollingFunctionMissingSome-300x260.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/NPCPollingFunctionMissingSome-480x416.png 480w\" sizes=\"(max-width: 508px) 100vw, 508px\" \/><figcaption>Only 11 NPC addresses are being polled.<\/figcaption><\/figure><\/div>\n\n\n\n<p>There are a number of NPC location structures being accessed consistently here, however there are more than 11 NPCs on the screen at the moment. Perhaps these 11 addresses belong to NPCs that are actually morphing, though it is rather dark and hard to see in the feast hall.<\/p>\n\n\n\n<p>We&#8217;re going to need to see if there&#8217;s a more suitable NPC coordinate polling function. We want to find code that is accessing NPC coordinates with an execution rate similar to the one we were using, and we want it to not be affected by whether or not the NPC is moving. <\/p>\n\n\n\n<p>We&#8217;ll be looking for the new function by looking at what other functions are accessing one of the addresses shown in the above image. We&#8217;ll be looking at what addresses <em>those<\/em> functions access, and we&#8217;ll be choosing the first one we find that is accessing more than 11, while still appearing to only be accessing NPC coordinates (and not coordinates of a snowflake or something).<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"651\" height=\"638\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/NewNPCCoordinatePolls.png\" alt=\"Shows a list of new potential NPC coordinate polling functions to choose from.\" class=\"wp-image-995\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/NewNPCCoordinatePolls.png 651w, https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/NewNPCCoordinatePolls-300x294.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/NewNPCCoordinatePolls-480x470.png 480w\" sizes=\"(max-width: 651px) 100vw, 651px\" \/><figcaption>These functions are polling NPC coordinates. The highlighted instruction is the currently used one.<\/figcaption><\/figure><\/div>\n\n\n\n<p>There are a number of functions to choose from. It is important to note that the one we&#8217;re currently using (highlighted in the image) only has an execution count of 420 whereas there are a few other functions with a much higher number of executions. <\/p>\n\n\n\n<p>If we <em>do<\/em> end up choosing a function with a higher execution rate, we&#8217;ll need to account for that by adjusting the number of morph steps on average for each morph cycle (otherwise morph cycles will occur much too fast).<\/p>\n\n\n\n<p>Looking at the first instruction on the list, it is accessing 87 addresses. That&#8217;s far too many. This trend continues with the second and third instructions. The fourth instruction, however, is accessing only 20. Is that enough? <\/p>\n\n\n\n<p>Let&#8217;s try to do an NPC headcount&#8230;it&#8217;s so difficult to see in this dark room! I&#8217;m having trouble getting an exact count, but there&#8217;s at least 30+, so we still need to keep on looking.<\/p>\n\n\n\n<p>Looking through the rest of the instructions, we see a number of them accessing 20 addresses, some accessing 140 addresses, etc. Nothing that perfectly fits. Reviewing everything I just observed, it seems that all of them are accessing either too few or too many addresses. Out of all the ones accessing too many, the ones accessing the least were the first and third instructions we looked at.<\/p>\n\n\n\n<p>The first instruction in the list is executing at approximately four times the current one&#8217;s execution rate, whereas the third instruction is executing at the same rate. So, let&#8217;s hook our Abomnification initiation point into the area of code the third instruction lives in.<\/p>\n\n\n\n<h4><span class=\"ez-toc-section\" id=\"Updated_Abomnification_Initiation_Point_Hook\"><\/span>Updated Abomnification Initiation Point Hook<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Initiates the Abomnification system.\n\/\/ UNIQUE AOB: 0F 10 40 30 0F 29 45 00 0F 28\ndefine(omnifyAbomnificationHook, &quot;ACValhalla.exe&quot; + E80275)\n\nassert(omnifyAbomnificationHook, 0F 10 40 30 0F 29 45 00)\nalloc(initiateAbomnification,$1000, omnifyAbomnificationHook)\n\nregistersymbol(omnifyAbomnificationHook)\n\ninitiateAbomnification:\n  pushf\n  \/\/ Ensure that the player location struct has been initialized.\n  push rbx\n  mov rbx,playerLocation\n  cmp [rbx],0\n  pop rbx\n  je initiateAbomnificationOriginalCode \n  \/\/ Back up the registers used to hold return values.\n  push rax\n  push rbx\n  push rcx\n  \/\/ The addresses in this function are aligned so that the coordinates\n  \/\/ begin at 0x30, whereas their alignment in most of the other places we \n  \/\/ work with them is such that the coordinates start at 0x50.\n  add rax,-20\n  \/\/ Ensure that the player isn't going to be Abomnified.\n  mov rbx,playerLocation\n  mov rcx,[rbx]\n  cmp rcx,rax\n  je initiateAbomnificationExit\n  \/\/ Push the identifying address parameter and call the Abomnification system.  \n  push rax\n  call executeAbomnification    \ninitiateAbomnificationExit:\n  \/\/ Restore the preserved values on the stack.\n  pop rcx\n  pop rbx\n  pop rax\ninitiateAbomnificationOriginalCode:\n  popf\n  movups xmm0,[rax+30]\n  movaps [rbp+00],xmm0\n  jmp initiateAbomnificationReturn\n\n\nomnifyAbomnificationHook:\n  jmp initiateAbomnification\n  nop 3\ninitiateAbomnificationReturn:\n<\/pre>\n\n\n<p>After saving the changes and re-applying our hack, everything is working like a charm! All dancing villagers were merrily morphing.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"1007\" height=\"629\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/TerrifyingDancing.png\" alt=\"Shows dancing villagers looking very creepy due to Abomnification morphing.\" class=\"wp-image-996\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/TerrifyingDancing.png 1007w, https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/TerrifyingDancing-300x187.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/TerrifyingDancing-768x480.png 768w, https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/TerrifyingDancing-480x300.png 480w\" sizes=\"(max-width: 1007px) 100vw, 1007px\" \/><figcaption>Dancing villagers are now morphing. Terrifying.<\/figcaption><\/figure><\/div>\n\n\n\n<p>With this fix in, I must say that everything is looking <em>fantastic<\/em>. Holy crap, the morphing is spectacular here in this opening scene. There&#8217;s going to be so many amazing moments on stream! All randomly determined of course haha. It looks really freaky when the adults come up to the kid and put their misshapen hands around his head, etc. <\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"More_Tiny_Dancing_People_Issues\"><\/span>More Tiny Dancing People Issues<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>I do notice that there are a number of dancers in this scene that are all <em>smallified<\/em> &#8212; which is essentially when the <em>static unnatural<\/em> morphing mode has been selected for a creature, and the static randomly determined size is beneath a threshold; this results in an even greater reduction in size in order to exaggerate the smallness.<\/p>\n\n\n\n<p>Back to my observation: I noticed a number of NPCs are all using this same morphing mode, with what appears to be the same determined size. Either their coordinates are still not being hit in the initiation point method, or we&#8217;re getting morph scale data lookup collisions with the new morph scale data resolution method.<\/p>\n\n\n\n<p>I&#8217;m only seeing this for a small number of NPCs, all next to each other and in a dancing line. In order to see if it is due to lookup collision, I restart the program. If it&#8217;s still the same NPCs, all still small, then the chances of a lookup collision are extraordinarily tiny.<\/p>\n\n\n\n<p>After restarting the program, I observe that they are indeed all still small. This is a bit perplexing. Even if all of these NPCs only received a single Abomnification initiation call, they should all be stuck at random sizes, not all at a small size. To get to the bottom of this, we&#8217;re going to want to look at what the Abomnification system is returning and for what location addresses.<\/p>\n\n\n\n<p>Looking at the <code>getAbomnifiedScales<\/code> function, I look at all the addresses being accessed by the instruction <code>mov eax,[rdx+04]<\/code>. This is the instruction that is responsible for loading the Abomnified width scale for a creature.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"483\" height=\"539\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/ZeroScales.png\" alt=\"Shows zero multiplier scales being returned for some characters.\" class=\"wp-image-998\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/ZeroScales.png 483w, https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/ZeroScales-269x300.png 269w, https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/ZeroScales-480x536.png 480w\" sizes=\"(max-width: 483px) 100vw, 483px\" \/><figcaption>Uh oh, a bunch of the NPCs are getting 0x scale multipliers.<\/figcaption><\/figure><\/div>\n\n\n\n<p>Oops. A bunch of NPCs are essentially getting 0x scale multipliers. It has nothing to do with static unnatural smallified morphing modes at all! Although it does bring up a semi-related issue to smallified creatures, but we&#8217;ll touch on that later.<\/p>\n\n\n\n<p>After writing down the location coordinates for one of these NPCs, I found that they are unfortunately not being hit up by our new NPC location polling function.<\/p>\n\n\n\n<p>Ahh what a shame. So, our new initiation point hook includes much, much more of the NPCs appearing on screen, but it still isn&#8217;t hitting up all of them. So, we&#8217;re going to have to try&#8230;.once again. This time, at least, I have one of those dancing, stationary NPCs coordinates, so let&#8217;s see what functions are accessing them.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"651\" height=\"638\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/NewNPCCoordinatePollsRound2.png\" alt=\"Shows yet another list of instructions accessing some NPC coordinates.\" class=\"wp-image-999\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/NewNPCCoordinatePollsRound2.png 651w, https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/NewNPCCoordinatePollsRound2-300x294.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/NewNPCCoordinatePollsRound2-480x470.png 480w\" sizes=\"(max-width: 651px) 100vw, 651px\" \/><figcaption>We see a smaller list of functions accessing the stationary NPC&#8217;s coordinates.<\/figcaption><\/figure><\/div>\n\n\n\n<p>Alright, we have a list of NPC coordinate polling functions which is more refined than the one we had earlier. For whatever reason, these stationary, dancing NPCs were not being covered by some of the earlier polling functions; but, now that we have this list, we can ensure all NPCs are covered by looking for the instructions that show up both on this list and the one from earlier.<\/p>\n\n\n\n<p>The first instruction highlighted here was also on the first list of location polling functions, and it also happened to have the same rate of execution as the function we&#8217;re hooking into now. Looking at the number of addresses this one is accessing, we get 114 addresses vs the 87 addresses being accessed by the older function.<\/p>\n\n\n\n<p>Alright. Let&#8217;s update the Abomnification initiation point&#8230;one (hopefully) more time.<\/p>\n\n\n\n<h4><span class=\"ez-toc-section\" id=\"Final_()_Abomnification_Initiation_Point_Hook\"><\/span>Final (?) Abomnification Initiation Point Hook<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Initiates the Abomnification system.\n\/\/ UNIQUE AOB: 0F 10 56 50 4C 8D 4C 24 30\ndefine(omnifyAbomnificationHook, &quot;ACValhalla.exe&quot; + 28117E0)\n\nassert(omnifyAbomnificationHook, 0F 10 56 50 4C 8D 4C 24 30)\nalloc(initiateAbomnification,$1000, omnifyAbomnificationHook)\n\nregistersymbol(omnifyAbomnificationHook)\n\ninitiateAbomnification:\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 initiateAbomnificationOriginalCode \n  \/\/ Back up the registers used to hold return values.\n  push rax\n  push rbx\n  push rcx\n  \/\/ Ensure that the player isn't going to be Abomnified.\n  mov rax,playerLocation\n  mov rbx,[rax]\n  cmp rbx,rsi\n  je initiateAbomnificationExit\n  \/\/ Push the identifying address parameter and call the Abomnification system.  \n  push rsi\n  call executeAbomnification    \ninitiateAbomnificationExit:\n  \/\/ Restore the preserved values on the stack.\n  pop rcx\n  pop rbx\n  pop rax\ninitiateAbomnificationOriginalCode:\n  popf\n  movups xmm2,[rsi+50]\n  lea r9,[rsp+30]\n  jmp initiateAbomnificationReturn\n\n\nomnifyAbomnificationHook:\n  jmp initiateAbomnification\n  nop 4\ninitiateAbomnificationReturn:\n<\/pre>\n\n\n<p>Because the location structure is aligned more closely to how we use it in other places, we were able to remove the location structure realignment part of the code.<\/p>\n\n\n\n<p>After plugging in this new code, <em>all<\/em> visible NPCs were morphing! Eureka! Everything is fantastic now! <\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Default_Scales_for_Lookup_Fails\"><\/span>Default Scales for Lookup Fails<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>One other issue brought to my attention by the tiny dancing people was the fact that a scale multiplier of 0x is returned if a creature doesn&#8217;t have any morphing scale data registered.<\/p>\n\n\n\n<p>While this is somewhat useful in bringing to my attention NPCs whose coordinates aren&#8217;t being covered by the Abomnification initiation point, I would rather that a creature simply retain its normal dimensions if something isn&#8217;t working right &#8212; especially given that I&#8217;d prefer any bumpiness incurred from unforeseen problems reduced as much as possible when streaming this live.<\/p>\n\n\n\n<p>This requires changes to the <code>getAbomnifiedScales<\/code> function found in the Omnified framework. I&#8217;ll just go over the particular changes since Omnified system code is under the purview of <a href=\"https:\/\/badecho.com\/index.php\/category\/omnified-design\/\" target=\"_blank\" rel=\"noreferrer noopener\">Omnified Design<\/a> articles, and I still need to write one for the Abomnification system. And I will soon!<\/p>\n\n\n\n<h4><span class=\"ez-toc-section\" id=\"getAbomnifiedScales_Unregistered_Morphing_Scale_Data_Update\"><\/span>getAbomnifiedScales Unregistered Morphing Scale Data Update<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n.\n.\n.\n  mov eax,[rdx+4]\n  mov ebx,[rdx+8]\n  mov ecx,[rdx+C]\n  \/\/ Check if we are getting empty data for return values. \n  \/\/ If so, we'll return default values instead.\n  cmp eax,0\n  je getAbomnifiedScalesDefault\n  jmp getAbomnifiedScalesCleanup  \ngetAbomnifiedScalesDefault:\n  mov eax,[defaultScaleX]\n  mov ebx,[defaultScaleX]\n  mov ecx,[defaultScaleX]\ngetAbomnifiedScalesCleanup:\n  pop rdx\n  ret 8\n<\/pre>\n\n\n<p>Now if there are any morphing mishaps on stream then at least the character will be normally sized. Hopefully there won&#8217;t be any mishaps though!<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Smallified_Is_Too_Small\"><\/span>Smallified Is Too Small<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Another issue brought up by the 0x scale problem had to do with how smallified NPCs were most likely going to end up being too small for my taste. The issue here has to do with the clothes of the NPCs; basically, clothes scale with the rest of the body, up to a certain point. Once the body starts getting too small, the clothes, or at least part of the clothes, stop getting smaller.<\/p>\n\n\n\n<p>So you end up basically with a tiny bundle of clothes running around, unable to actually see the tiny NPC inside that bundle. It sort of ruins the point of the smallified morph mode, which is to have a super tiny NPC&#8230;not a tiny NPC with big clothes.<\/p>\n\n\n\n<p>The reason behind the tiny NPC in clothing bundle problem has to do with the existence of a specific scaling routine for a particular section of clothes. I stumbled onto a dedicated rendering function for this very thing when searching for what ended up being the code we hooked the Abomnification scale application hook into.<\/p>\n\n\n\n<p>I&#8217;m not going to bother adding an additional hook into this clothing function, instead I&#8217;m just going to tweak the <code>unnaturalSmallX<\/code> parameter, which controls how much the NPC gets smallified during&#8230;smallification. Currently, it is set to the default, which is <strong>0.3<\/strong>. <\/p>\n\n\n\n<p>Static unnatural morphs are uniform in nature, with limits set by the <code>abominifyHeightResultLower<\/code> and <code>abominifyHeightResultUpper<\/code> parameters, with the upper limit being set to 1.6x for this game. The intent behind smallification is for it to give us a noticeably tinier creature. So, given that the upper height limit has been reduced for the game, we have a bit more latitude as far as the <code>unnaturalSmallX<\/code> parameter goes.<\/p>\n\n\n\n<p>If we want to achieve a 90% normal size when the maximum possible height is rolled, then we&#8217;ll want to use an <code>unnaturalSmallX<\/code> parameter value of <strong>0.5625<\/strong>. This isn&#8217;t really perfect, as 90% size is too close to the normal size&#8230;we might just have to change how we do the static unnatural morphing mode in general, where we have a specific range of small and\/or big sizes we generate for.<\/p>\n\n\n\n<p>We&#8217;ll explore that possibility if we need to. Until then&#8230;<\/p>\n\n\n\n<h4><span class=\"ez-toc-section\" id=\"Updated_Abomnification_External_Parameters\"><\/span>Updated Abomnification External Parameters<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nabominifyWidthResultUpper:\n  dd #250\n  \nabominifyHeightResultUpper:\n  dd #160\n  \nabominifyDepthResultUpper:\n  dd #200\n  \nunnaturalSmallX:\n  dd (float)0.5625\n<\/pre>\n\n\n<p>This may require additional tweaking, or the additional logic I alluded to just a bit ago.<\/p>\n\n\n\n<p>With all of this done, I confidently proceeded to join in the festivities at the feast hall, and finished the opening scenario in the game without any further incident. Yay.<\/p>\n\n\n\n<h2><span class=\"ez-toc-section\" id=\"Grown_Up_Viking_Man\"><\/span>Grown Up Viking Man<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>With the opening sequence completed, we&#8217;re now playing the game as the grown up Viking hero guy. Eivar, I think his name is. The playtest will continue until we get past the first few combats are so, which will give us some good opportunities to see if everything is tuned correctly in that regard.<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Tuning_the_Damage\"><\/span>Tuning the Damage<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Right away, after the first combat, it became evident to me that it will be best to play this on Normal difficulty, otherwise we&#8217;re going to get a lot of one shots from the <em>extra damage<\/em> Apocalypse effect. One shots should really only occur for the <em>sixty nine damage<\/em> Apocalypse effect.<\/p>\n\n\n\n<p>As far as I understand, it seems that the difficulty options in the game only affect the enemy health and damage. I will play games at a higher difficulty if it affects things like AI and all that, but I refuse to play difficulties that just make enemies &#8220;bullet sponges&#8221;. The best kind of difficulty is one where you die fast and enemies die fast.<\/p>\n\n\n\n<p>Conversely, it seems like enemies do way too little damage on average with Normal difficulty when using the stock extra damage multiplier of <strong>2.0<\/strong>. I really think it will need to be raised to <strong>3.0<\/strong> instead. Doing so will cause the average damage increase for this game to be 3x then. Not including all those insane sixty nine and teleportitis-to-our-death damage amounts, of course.<\/p>\n\n\n\n<p>Toasty.<\/p>\n\n\n\n<h4><span class=\"ez-toc-section\" id=\"Updated_Apocalypse_External_Parameters\"><\/span>Updated Apocalypse External Parameters<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nnegativeVerticalDisplacementEnabled:\n  dd 0\n  \nteleportitisDisplacementX:\n  dd (float)5.0\n  \nyIsVertical:\n  dd 0\n    \nextraDamageX:\n  dd (float)3.0\n<\/pre>\n\n\n<p>Triple damage on Normal difficulty <em>might<\/em> be perfect. A strong (charged) attack from an enemy did the following damage to the character:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>16:01-Enemy rolls a 3: 3x DAMAGE causing 96 damage to the player!\nPlayer now has 4 health.<\/code><\/pre>\n\n\n\n<p>So it <em>almost<\/em> killed the character. Obviously, if I had anything much less than 100% health, I would&#8217;ve been dead. Remember, we removed the one hit kill protection from this game, which would protect against dying from something like that.<\/p>\n\n\n\n<p>In comparison, this is the damage logged from a single strong attack while we were on the hardest difficulty:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>15:50-Enemy rolls a 7: RISK OF MURDER!\n15:50-Enemy rolls a 3: WHEW! Just normal damage causing 74 damage to the player!\nPlayer now has 26 health.<\/code><\/pre>\n\n\n\n<p>We were lucky here, and got a normal damage roll. We would&#8217;ve been murdered regardless of our health if we hit the most common effect (extra damage). So, the 3x damage on normal difficulty is an improvement, however it leaves very little breathing room. <\/p>\n\n\n\n<p>Despite the tiny breathing room, I believe it just might be perfect, and gives us incentive for making sure our health is topped off at all times. If I&#8217;m asked by a viewer what difficulty I&#8217;m playing on, I&#8217;ll be sure to say &#8220;Omnified difficulty&#8221;, as this is <em>nothing<\/em> even close to Normal.<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Fake_Tom_Petty_Teleportitis_Glitchin%E2%80%99\"><\/span>Fake Tom Petty: Teleportitis Glitchin&#8217;<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>In an Omnified game, a clip from Tom Petty&#8217;s <em>Free Fallin&#8217;<\/em> plays if the character is hit and receives a teleportitis effect such that it will result in them falling to their death. Pretty cool. Anyway, I noticed some instances of Tom Petty singing without any sort of falling death actually occurring.<\/p>\n\n\n\n<p>Unacceptable.<\/p>\n\n\n\n<p>Looking at the Apocalypse log, we see that the player <em>should<\/em> have definitely fallen to their death:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>16:10-Enemy rolls a 5: SUDDEN TELEPORTITIS (40.209999084473) causing 32 damage to the player!\nPlayer now has 68 health.<\/code><\/pre>\n\n\n\n<p>The number in parenthesis represents the vertical shift in the player&#8217;s Z coordinate that should&#8217;ve happened. The player was supposed to have been launched up 40 units into the sky, which is <em>way<\/em> off the ground. In reality however, no kind of shift happened at all.<\/p>\n\n\n\n<p>This means that the teleportation was a dud. I&#8217;ve seen this sort of thing before in one other game I&#8217;ve Omnified: <em>Dark Souls<\/em> (the first one). Basically, any modification of the player&#8217;s coordinates during specific animations, in particular animations occurring when getting smacked around, would be ignored.<\/p>\n\n\n\n<p>The reason why our teleportitis coordinates were being ignored in <em>Dark Souls<\/em> can be best illustrated by listing the sequence of events that would play out:<\/p>\n\n\n\n<ol><li>The player is about to receive some damage.<\/li><li>Apocalypse system takes over, and determines that a teleportitis is going to occur. The player&#8217;s coordinates are directly manipulated to the new location the player is being teleported to.<\/li><li>A &#8220;receiving damage&#8221; animation begins on the player in response to some damage.<\/li><li>The location update code is executed as normal (basically, like in most games, in response to a <em>tick<\/em>, a timed event) with new coordinate values based on where the character should be due to the damage animation.<\/li><li>The damage animation coordinate values are calculated based on the character&#8217;s position before receiving the damage. They are committed to memory, overwriting our teleportitis-based coordinates.<\/li><\/ol>\n\n\n\n<p>The way we worked around this with <em>Dark Souls<\/em> was to have a <code>teleported<\/code> flag set after a teleportitis effect went off, which would then result in the next execution of the location update code in the game to be ignored. <\/p>\n\n\n\n<p>The <code>teleported<\/code> flag would then be reset and everything would continue on as normal, as the &#8220;receiving damage&#8221; animation would, from that point on, be based on the coordinates set during the teleportitis effect, not the coordinates as they were prior to receiving the damage.<\/p>\n\n\n\n<p>From observations made during the <a href=\"https:\/\/badecho.com\/index.php\/2020\/12\/20\/hacking-ac-valhalla-part-3\/\" target=\"_blank\" rel=\"noreferrer noopener\">implementation of the Predator system<\/a>, there is only one function in code responsible for updating the location coordinates of a creature. Would implementing a similar workaround work for <em>Assassin&#8217;s Creed: Valhalla<\/em>? It might, and it might not. Let&#8217;s try it out.<\/p>\n\n\n\n<h4><span class=\"ez-toc-section\" id=\"Bypass_Teleportitis_Overwrite_Hook\"><\/span>Bypass Teleportitis Overwrite Hook<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Bypasses a single location update pulse so that coordinates changes\n\/\/ from a teleportitis effect are not overwritten.\n\/\/ Unique AOB: 0F 28 48 30 0F 29 49 50\ndefine(omnifyBypassTeleportitisOverwriteHook, &quot;ACValhalla.exe&quot; + 7E9D8A)\n\nassert(omnifyBypassTeleportitisOverwriteHook,0F 28 48 30 0F 29 49 50)\nalloc(bypassTeleportitisOverwrite,$1000,omnifyBypassTeleportitisOverwriteHook)\n\nregistersymbol(omnifyBypassTeleportitisOverwriteHook)\n\nbypassTeleportitisOverwrite:\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 bypassTeleportitisOverwriteOriginalCode  \n  \/\/ Backup registers used to hold the player's location structures.\n  push rax\n  push rbx\n  push rdx\n  \/\/ Backup the &quot;updated location&quot; structure address.\n  mov rdx,rax\n  mov rax,playerLocation\n  mov rbx,[rax]\n  \/\/ If the player is the one moving, we make sure that any new coordinates\n  \/\/ resulting from a recent teleport stick for one additional location\n  \/\/ update tick.\n  cmp rbx,rcx\n  jne bypassTeleportitisOverwriteExit\n  mov rax,teleported\n  cmp [rax],1\n  jne bypassTeleportitisOverwriteExit\n  \/\/ Clear the flag so this only happens once.\n  mov [rax],0\n  \/\/ Take the current coordinates and store them in the &quot;updated location&quot; \n  \/\/ structure used in the original code as the source for the new coordinates.\n  movups xmm1,[rcx+50]\n  movups [rdx+30],xmm1\nbypassTeleportitisOverwriteExit:  \n  \/\/ Restore backed up values.\n  pop rdx\n  pop rbx\n  pop rax\nbypassTeleportitisOverwriteOriginalCode:\n  popf\n  movaps xmm1,[rax+30]\n  movaps [rcx+50],xmm1\n  jmp bypassTeleportitisOverwriteReturn\n\nomnifyBypassTeleportitisOverwriteHook:\n  jmp bypassTeleportitisOverwrite\n  nop 3\nbypassTeleportitisOverwriteReturn:\n<\/pre>\n\n\n<p>This is a new hook that actually hooks directly into the location update code. The Predator system, if you remember, always hooks into the movement application code (ideally at least), which means the location update code, until now, was free for the hookin&#8217;.<\/p>\n\n\n\n<p>After writing up this hack and plugging it in, it appears (6 teleports or so later) that everything is working great! Hell yeah! No more fake Tom Petty! I am very pleased to see the exact same type of workaround that worked for <em>Dark Souls<\/em> also worked for this.<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Double_Dipping_Apocalypse_From_Fall_Damage\"><\/span>Double Dipping Apocalypse From Fall Damage<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>It was while I was fixing the teleportitis issue that I noticed another problem popping out at my face: the Apocalypse system was being triggered by fall damage.<\/p>\n\n\n\n<p>This shouldn&#8217;t have been a surprise, but Apocalypse-triggering fall damage is something I always I forget to check for and address during initial Apocalypse implementation. In some games the execution path for both falling damage and damage from an enemy is the same, and in some games it is not. Hard to give statistics here off the top of my head.<\/p>\n\n\n\n<p>Well anyways, this is one of those games where it is the former case. Usually it is much too punishing to allow for fall damage to trigger an Apocalypse roll, as it makes normal leaps (which often the game can force you into making) potentially fatal. We&#8217;re going to have to filter fall damage out.<\/p>\n\n\n\n<p>If you don&#8217;t remember, we found a place on the stack during <a href=\"https:\/\/badecho.com\/index.php\/2020\/12\/14\/hacking-ac-valhalla-part-2\/\" target=\"_blank\" rel=\"noreferrer noopener\">Apocalypse implementation<\/a> where the root structure for the character responsible for doing the damage is stored. Well&#8230;fall damage shouldn&#8217;t have any kind of root structure, so I wonder what will be on the stack when we&#8217;re getting hurt because of a fall?<\/p>\n\n\n\n<p>After placing a breakpoint in our Apocalypse hook and falling down, it was as I hoped: nothing. There is no address in the damage source location on the stack if we&#8217;ve fallen. So, we&#8217;ll just filter that scenario out.<\/p>\n\n\n\n<h4><span class=\"ez-toc-section\" id=\"Updated_Apocalypse_Initiation_Point_Hook\"><\/span>Updated Apocalypse Initiation Point Hook<span class=\"ez-toc-section-end\"><\/span><\/h4>\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; + 213DA31)\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]\n  \/\/ If no root structure is listed as the damage source, this means\n  \/\/ that the damage is from an ambient source (i.e. falling), which\n  \/\/ we want to prevent from triggering the Apocalypse system.\n  cmp rcx,0\n  je initiateApocalypseExit\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  \/\/ Realign the player's coordinates so it begins at the X coordinate.\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 rbx\n  pop rcx\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<\/pre>\n\n\n<p>With the new code in, fall damage no longer triggers any Apocalypse rolls! And&#8230;it appears all other damage is still being correctly processed! Hope I don&#8217;t get bit on the butt by any last minute edge cases.<\/p>\n\n\n\n<h2><span class=\"ez-toc-section\" id=\"Playtest_Complete\"><\/span>Playtest Complete<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Alright. Think we&#8217;ve fixed all the immediate issues. If there are any other issues, I guess I&#8217;ll have to fix them live! Things seem super playable! I&#8217;m going to update my graphics drivers and do one more quick and tiny playthrough (just in case lol), but other than that, I think we&#8217;re good to go!<\/p>\n\n\n\n<p>I cannot wait to play this game! Omnified <em>Assassin&#8217;s Creed: Valhalla<\/em> is going to be quite the trip. Catch it live on my stream at: <a href=\"https:\/\/twitch.tv\/omni\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/twitch.tv\/omni<\/a><\/p>\n\n\n\n<p>See ya there.<\/p>\n\n\n\n<p><em>~Omni<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Table of Contents Giving Omnified AC: Valhalla Some Good Ole Testin&#8217;Living That Toddler Viking LifeDancing People Morphed, but Not MorphingUpdated [&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,40],"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 5 (Playtesting) - 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 as a result of playtesting off 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\/2020\/12\/31\/hacking-ac-valhalla-part-5\/\" \/>\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 5 (Playtesting) - 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 as a result of playtesting off stream.\" \/>\r\n<meta property=\"og:url\" content=\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/\" \/>\r\n<meta property=\"og:site_name\" content=\"omni&#039;s hackpad\" \/>\r\n<meta property=\"article:published_time\" content=\"2020-12-31T23:55:05+00:00\" \/>\r\n<meta property=\"article:modified_time\" content=\"2021-01-13T01:07:52+00:00\" \/>\r\n<meta property=\"og:image\" content=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/NPCPollingFunctionMissingSome.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\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/12\/NPCPollingFunctionMissingSome.png\",\"width\":508,\"height\":440,\"caption\":\"Only 11 NPC addresses are being polled.\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#webpage\",\"url\":\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/\",\"name\":\"Hacking Assassin's Creed: Valhalla - Part 5 (Playtesting) - omni&#039;s hackpad\",\"isPartOf\":{\"@id\":\"https:\/\/badecho.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#primaryimage\"},\"datePublished\":\"2020-12-31T23:55:05+00:00\",\"dateModified\":\"2021-01-13T01:07:52+00:00\",\"description\":\"An overview of changes and fixes made to Omnified Assassin's Creed: Valhalla as a result of playtesting off stream.\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/\"]}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#webpage\"},\"author\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"headline\":\"Hacking Assassin&#8217;s Creed: Valhalla &#8211; Part 5 (Playtest Fixes)\",\"datePublished\":\"2020-12-31T23:55:05+00:00\",\"dateModified\":\"2021-01-13T01:07:52+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#webpage\"},\"publisher\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"image\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2020\/12\/31\/hacking-ac-valhalla-part-5\/#primaryimage\"},\"keywords\":\"Hacking,Omnifying,Playtesting\",\"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\/991"}],"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=991"}],"version-history":[{"count":6,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/991\/revisions"}],"predecessor-version":[{"id":1004,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/991\/revisions\/1004"}],"wp:attachment":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/media?parent=991"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/categories?post=991"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/tags?post=991"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}