{"id":1477,"date":"2021-04-12T08:17:16","date_gmt":"2021-04-12T13:17:16","guid":{"rendered":"https:\/\/badecho.com\/?p=1477"},"modified":"2021-08-25T13:26:34","modified_gmt":"2021-08-25T18:26:34","slug":"hacking-witcher-part-2","status":"publish","type":"post","link":"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/","title":{"rendered":"Hacking The Witcher 3 &#8211; Part 2 (Apocalypse System)"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"366\" height=\"181\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/WitcherLogo-e1617575127960.png\" alt=\"\" class=\"wp-image-1444\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/WitcherLogo-e1617575127960.png 366w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/WitcherLogo-e1617575127960-300x148.png 300w\" sizes=\"(max-width: 366px) 100vw, 366px\" \/><\/figure><\/div>\n\n\n\n<p>Now that we&#8217;ve had the opportunity to do some <a href=\"https:\/\/badecho.com\/index.php\/2021\/04\/04\/hacking-witcher-part-1\/\" target=\"_blank\" rel=\"noreferrer noopener\">basic analysis of the data structures<\/a> for <em>The Witcher 3<\/em>, it&#8217;s time to uproot its gameplay and get things going in the crazy <a href=\"https:\/\/badecho.com\/index.php\/what-is-omnified\/\" target=\"_blank\" rel=\"noreferrer noopener\">Omnified<\/a> department by throwing in the <a href=\"https:\/\/badecho.com\/index.php\/2020\/10\/19\/apocalypse-system\/\" target=\"_blank\" rel=\"noreferrer noopener\">Apocalypse system<\/a>. This will completely overhaul the damage system and I think end up being a huge improvement to the game, as its biggest defect, for me at least, has always been its difficulty (or lack thereof).<\/p>\n\n\n\n<p>For detailed information on what the Apocalypse system is, you can read the <a href=\"https:\/\/badecho.com\/index.php\/2020\/10\/19\/apocalypse-system\/\" target=\"_blank\" rel=\"noreferrer noopener\">design article on it here<\/a>, or if you don&#8217;t like reading, feel free to watch this nice little video:<\/p>\n\n\n\n<figure class=\"wp-block-embed aligncenter is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"What is Apocalypse?\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/pUzMjc4UO4A?feature=oembed&amp;wmode=opaque\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe>\n<\/div><figcaption>Don&#8217;t be scared &#8212; here&#8217;s a summary on the Apocalypse system.<\/figcaption><\/figure>\n\n\n\n<p>Let&#8217;s begin then by doing a bit of reverse engineering to find the points in the code we need to hook into in order to make this magic happen.<\/p>\n\n\n\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\/2021\/04\/12\/hacking-witcher-part-2\/#On_the_Matter_of_the_Damage_Application_Code\" title=\"On the Matter of the Damage Application Code\">On the Matter of the Damage Application Code<\/a><ul class=\"ez-toc-list-level-3\"><li class=\"ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Tracing_the_Damage_Application_Code\" title=\"Tracing the Damage Application Code\">Tracing the Damage Application Code<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#On_the_Matter_of_Hit_Detection\" title=\"On the Matter of Hit Detection\">On the Matter of Hit Detection<\/a><ul class=\"ez-toc-list-level-3\"><li class=\"ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Types_of_Values_Processed_by_the_Damage_Application_Code\" title=\"Types of Values Processed by the Damage Application Code\">Types of Values Processed by the Damage Application Code<\/a><\/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\/2021\/04\/12\/hacking-witcher-part-2\/#Filtering_Out_All_Operations_Unrelated_to_W3AbilityManager\" title=\"Filtering Out All Operations Unrelated to W3AbilityManager\">Filtering Out All Operations Unrelated to W3AbilityManager<\/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\/2021\/04\/12\/hacking-witcher-part-2\/#W3AbilityManager_Filter_Code\" title=\"W3AbilityManager Filter Code\">W3AbilityManager Filter Code<\/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\/2021\/04\/12\/hacking-witcher-part-2\/#Filtering_Out_All_Operations_Unrelated_to_Damage_to_Player\" title=\"Filtering Out All Operations Unrelated to Damage to Player\">Filtering Out All Operations Unrelated to Damage to Player<\/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\/2021\/04\/12\/hacking-witcher-part-2\/#Player_Hit_Detection_Code\" title=\"Player Hit Detection Code\">Player Hit Detection Code<\/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\/2021\/04\/12\/hacking-witcher-part-2\/#Determining_When_the_Player_Is_Damaging_an_Enemy\" title=\"Determining When the Player Is Damaging an Enemy\">Determining When the Player Is Damaging an Enemy<\/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\/2021\/04\/12\/hacking-witcher-part-2\/#Enemy_Hit_by_Player_Detection_Code\" title=\"Enemy Hit by Player Detection Code\">Enemy Hit by Player Detection Code<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#On_the_Matter_of_Ciri%E2%80%99s_Hit_Detection\" title=\"On the Matter of Ciri&#8217;s Hit Detection\">On the Matter of Ciri&#8217;s Hit Detection<\/a><ul class=\"ez-toc-list-level-4\"><li class=\"ez-toc-heading-level-4\"><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Player_Hit_Detection_Code_(Ciri)\" title=\"Player Hit Detection Code (Ciri)\">Player Hit Detection Code (Ciri)<\/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-13\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#On_the_Matter_of_Ciri%E2%80%99s_Coordinates\" title=\"On the Matter of Ciri&#8217;s Coordinates\">On the Matter of Ciri&#8217;s Coordinates<\/a><ul class=\"ez-toc-list-level-3\"><li class=\"ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Updated_Player_Root_Structure_Hook_With_Resolved_Location\" title=\"Updated Player Root Structure Hook With Resolved Location\">Updated Player Root Structure Hook With Resolved Location<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Adding_Apocalypse_Support_for_Coordinate_Doubles\" title=\"Adding Apocalypse Support for Coordinate Doubles\">Adding Apocalypse Support for Coordinate Doubles<\/a><ul class=\"ez-toc-list-level-3\"><li class=\"ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Updated_Teleportitis_Effect_Code_in_Omnified_Framework\" title=\"Updated Teleportitis Effect Code in Omnified Framework\">Updated Teleportitis Effect Code in Omnified Framework<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Writing_the_Apocalypse_Initiation_Hook\" title=\"Writing the Apocalypse Initiation Hook\">Writing the Apocalypse Initiation Hook<\/a><ul class=\"ez-toc-list-level-3\"><li class=\"ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Apocalypse_Initiation_Hook_%E2%80%93_Template\" title=\"Apocalypse Initiation Hook &#8211; Template\">Apocalypse Initiation Hook &#8211; Template<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Apocalypse_Initiation_Hook_%E2%80%93_First_Steps\" title=\"Apocalypse Initiation Hook &#8211; First Steps\">Apocalypse Initiation Hook &#8211; First Steps<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Apocalypse_Initiation_Hook_%E2%80%93_Player_Apocalypse\" title=\"Apocalypse Initiation Hook &#8211; Player Apocalypse\">Apocalypse Initiation Hook &#8211; Player Apocalypse<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-21\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Apocalypse_Initiation_Hook_%E2%80%93_Enemy_Apocalypse\" title=\"Apocalypse Initiation Hook &#8211; Enemy Apocalypse\">Apocalypse Initiation Hook &#8211; Enemy Apocalypse<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-22\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Apocalypse_Initiation_Hook_%E2%80%93_Return_Value_Processing_and_Cleanup\" title=\"Apocalypse Initiation Hook &#8211; Return Value Processing and Cleanup\">Apocalypse Initiation Hook &#8211; Return Value Processing and Cleanup<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-23\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Apocalypse_Initiation_Hook_%E2%80%93_External_Parameters\" title=\"Apocalypse Initiation Hook &#8211; External Parameters\">Apocalypse Initiation Hook &#8211; External Parameters<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-24\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Wrapping_Up\" title=\"Wrapping Up\">Wrapping Up<\/a><ul class=\"ez-toc-list-level-3\"><li class=\"ez-toc-heading-level-3\"><a class=\"ez-toc-link ez-toc-heading-25\" href=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#Apocalypse_Initiation_Hook_%E2%80%93_Complete\" title=\"Apocalypse Initiation Hook &#8211; Complete\">Apocalypse Initiation Hook &#8211; Complete<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\r\n<h2><span class=\"ez-toc-section\" id=\"On_the_Matter_of_the_Damage_Application_Code\"><\/span>On the Matter of the Damage Application Code<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>As always, implementing the Apocalypse system requires us to make an <em>initiation point<\/em> to be injected directly into the game&#8217;s <em>damage application<\/em> code. You can learn more about these terms and exactly what kind of code I&#8217;m talking about by checking out the <a href=\"https:\/\/badecho.com\/index.php\/2020\/10\/19\/apocalypse-system\/#player-apocalypse-initiation-point\" target=\"_blank\" rel=\"noreferrer noopener\">relevant section in my article on the Apocalypse system<\/a>.<\/p>\n\n\n\n<p>To start our search for the damage application code, we need to first find the <em>health update<\/em> code, which is simple enough: it&#8217;s the code responsible for updating our character&#8217;s health in memory to a newly calculated value following some kind of event (like getting your ass smacked by a drowner, etc.).<\/p>\n\n\n\n<p>So, to do that, we just need to right click on our player&#8217;s health in the address list and choose <strong>Find out what accesses this address<\/strong>. Then we get our butt smacked.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"734\" height=\"478\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic1.png\" alt=\"Shows the code that updates a players health to a new value.\" class=\"wp-image-1482\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic1.png 734w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic1-300x195.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic1-480x313.png 480w\" sizes=\"(max-width: 734px) 100vw, 734px\" \/><figcaption>Any change to our health is committed by this code.<\/figcaption><\/figure><\/div>\n\n\n\n<p>Above we can see what is undoubtedly our health update code. Most distressingly, however, I noticed right away that the health update code was getting pinged maybe 5-10+ times every time we got hit by an enemy. I&#8217;ve been doing this long enough to know that we were going to be in for a fun ride.<\/p>\n\n\n\n<p>And oh boy, were we in for one. <em>Spoiler alert<\/em>: this was undoubtedly one of the most complicated reverse engineering endeavors I&#8217;ve had to undertake in order to figure out whether our player was receiving damage or not.<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Tracing_the_Damage_Application_Code\"><\/span>Tracing the Damage Application Code<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Taking a look at where the health update code lives, we see the following code:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"1024\" height=\"593\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic2-1024x593.png\" alt=\"Shows the code and surrounding code that updates the player's health for all situations.\" class=\"wp-image-1483\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic2-1024x593.png 1024w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic2-300x174.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic2-768x445.png 768w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic2-480x278.png 480w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic2.png 1031w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>Here is the surrounding code for the health updates. We can see the code obtaining our vitals struct from our W3AbilityManager.<\/figcaption><\/figure><\/div>\n\n\n\n<p>Scrolling up from here, there is no immediate arithmetic operation that jumped out at me. So, as is the norm for most games, the updated health value was being calculated at a point most likely far removed from where it was getting committed to our player&#8217;s health in memory.<\/p>\n\n\n\n<p>If we&#8217;re lucky, maybe we&#8217;ll see something by going up the stack a bit.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"1024\" height=\"593\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic3-1024x593.png\" alt=\"Shows the method one level up on the stack to the health update code.\" class=\"wp-image-1484\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic3-1024x593.png 1024w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic3-300x174.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic3-768x445.png 768w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic3-480x278.png 480w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic3.png 1031w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>Here&#8217;s the dynamically addressed function call one level up from the health update code. &#8220;Thousands&#8221; of functions seem to be using this.<\/figcaption><\/figure><\/div>\n\n\n\n<p>We don&#8217;t see anything here of note, arithmetic-wise, but we do see a very disturbing instance of a dynamically addressed function call, only one level above our health update code! This means that there is probably going to be a lot of different kinds of code calling into this, making debugging and our reverse engineering efforts quite a pain.<\/p>\n\n\n\n<p>Indeed, if we place a breakpoint here, just one level up from our health update code, we can observe it getting hit at a near constant rate. Clearly it would appear that, much like the code we were dealing with in regards to <strong>W3AbilityManger <\/strong>resolution, that we were knee-deep in the middle of some highly generalized code. This is something I always strive for when writing my own code, but it also something quite painful to deal with at the assembly level when trying to look backwards in time.<\/p>\n\n\n\n<p>We were going to need to do a trace somewhere, but we were going to have to try to figure out how to filter all the threads of execution hitting this function up so we can produce meaningful results. Normally, when we do a trace, we go quite a few levels up on the stack, so let&#8217;s do that right now.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"1024\" height=\"791\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic4-1024x791.png\" alt=\"Shows a parent function call a few levels above the health update code from which we'll be starting a trace.\" class=\"wp-image-1485\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic4-1024x791.png 1024w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic4-300x232.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic4-768x593.png 768w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic4-480x371.png 480w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic4.png 1031w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>This is a number of calls up the chain from the health update code. We&#8217;re going to try to do a trace here &#8212; difficult since so many functions call it.<\/figcaption><\/figure><\/div>\n\n\n\n<p>This code here, which is calling <em>yet another<\/em> dynamically addressed function, is very far removed from the health update code. I believe this code is situated at the top of a few of the recursive chains of function calls that I observed. This was the ideal place to start our trace, as I was able to figure out a register value that we could discriminate health updates from other kinds of updates with; namely, the <code>r12<\/code> register being set to our <strong>W3AbilityManager<\/strong>.<\/p>\n\n\n\n<p>We learned from the previous article that this &#8220;property unroller&#8221; family of functions that we&#8217;re looking at stores the data source of values it&#8217;s working with in the <code>r12<\/code> register. Since our health comes from our ability manager, that is what we want to end up filtering on. So, we just look at what <code>[playerAbilityManager]<\/code> resolves to in our code, and set up a trace to go off when <code>r12<\/code> equals that.<\/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\/04\/ApocalypsePic7.png\" alt=\"Shows our trace results from the parent function that led to the health update code.\" class=\"wp-image-1488\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic7.png 946w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic7-300x169.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic7-768x433.png 768w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic7-480x270.png 480w\" sizes=\"(max-width: 946px) 100vw, 946px\" \/><figcaption>Here&#8217;s the beginning of our successful trace as to how damage gets applied to our health value.<\/figcaption><\/figure><\/div>\n\n\n\n<p>I cannot recall if we got a successful trace on our first try&#8230;but I think we did? Anyway, what we&#8217;re looking at here is the start of it, and as you can see, the first instruction is that very same dynamically addressed function call that was shown in the previous picture.<\/p>\n\n\n\n<p>We had to scroll through an uncountable number of function calls until we finally got to the meat of the matter: the damage application code.<\/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\/04\/ApocalypsePic8.png\" alt=\"Shows us the meat of the matter: the damage application code.\" class=\"wp-image-1489\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic8.png 946w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic8-300x169.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic8-768x433.png 768w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic8-480x270.png 480w\" sizes=\"(max-width: 946px) 100vw, 946px\" \/><figcaption>Here is the damage application code. However, it is used for MUCH more than just calculating new health values.<\/figcaption><\/figure><\/div>\n\n\n\n<p>There it is! In this instruction, the code is subtracting a damage amount stored in <code>[rsp+40]<\/code> from a creature&#8217;s current health amount, stored in <code>xmm0<\/code>. <\/p>\n\n\n\n<p>Well that wasn&#8217;t very difficult &#8212; I think it honestly took me only thirty minutes to find this. I was feeling pretty good. It didn&#8217;t take long for me to realize however, that this &#8220;damage&#8221; application code was actually being used to calculate differences for a <em>plethora <\/em>of kinds of values. Literally, from the player&#8217;s health getting damaged, to the position of elements on the screen&#8217;s HUD, to probably the space between Geralt&#8217;s chin hairs.<\/p>\n\n\n\n<p>That all meant we needed to devise some proper hit detection in order to be able to distinguish damage to the player (as well damage to the enemy) from all these other calculations.<\/p>\n\n\n\n<h2><span class=\"ez-toc-section\" id=\"On_the_Matter_of_Hit_Detection\"><\/span>On the Matter of Hit Detection<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Much time was spent on figuring out all the different sorts of values being processed by our &#8220;damage&#8221; application code &#8212; all of it was broadcast on my <a href=\"https:\/\/twitch.tv\/omni\" target=\"_blank\" rel=\"noreferrer noopener\">stream<\/a> (where I had the privilege to scratch my head going &#8220;HMMM&#8221; in front a bunch of people). So, if you are curious about the exact process in which I figured this all out, you&#8217;ll need to consult either a VOD from there or one of my <a href=\"https:\/\/youtube.com\/c\/omnittv\" target=\"_blank\" rel=\"noreferrer noopener\">YouTube<\/a> videos when I get around to uploading them.<\/p>\n\n\n\n<p><em>Please by advised that, although I tested this code out quite a bit, what we&#8217;re trying to achieve is a rather complicated affair. That means things might change in the future. If that happens, remember that I will always upload the latest version of my hacking source to my source repository at <a href=\"https:\/\/github.com\/BadEcho\/core\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/BadEcho\/core<\/a>.<\/em><\/p>\n\n\n\n<p>Lets take a look at the code in question.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"1024\" height=\"698\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic10-1024x698.png\" alt=\"Shows our damage application code, with execution paused during an actual damage application.\" class=\"wp-image-1491\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic10-1024x698.png 1024w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic10-300x205.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic10-768x524.png 768w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic10-480x327.png 480w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic10.png 1031w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>Shows execution paused during an actual damage application.<\/figcaption><\/figure><\/div>\n\n\n\n<p>This is where the magic happens. Even though this game lacks subtractive code specifically dedicated to damage being done to the health of entities, this is still one of the best places to hook the Apocalypse code into, as it ensures we get a say before anything is done with the game&#8217;s original damage.<\/p>\n\n\n\n<p>We could say that the only other better place to impact the damage is in the code that actually calculates the damage itself (where the health has no bearing), as that would ensure all possible dependent systems are corrected to use our adjusted damage value; however, the code responsible for that would be most likely missing some components required by the Apocalypse system (namely, the health the damage is being applied to). This would end up requiring multiple hooks into the code for Apocalypse initiation, etc.<\/p>\n\n\n\n<p>It&#8217;s something we can explore in the future.<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Types_of_Values_Processed_by_the_Damage_Application_Code\"><\/span>Types of Values Processed by the Damage Application Code<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Let&#8217;s talk quickly about all the different kinds of values I observed being operated on by this code. Remember, <em>every<\/em> single game I&#8217;ve put the Apocalypse system into so far had dedicated subtractive code for damage to health. As I said before, I&#8217;ve always been surprised to see such specific code for a gameplay matter; it is nice to see some actual generalized code in one of these games.<\/p>\n\n\n\n<p>I observed this code would be executed to process value changes of the type including, but not limited to:<\/p>\n\n\n\n<ul><li>damage to the player&#8217;s health,<\/li><li>damage to an enemy&#8217;s health,<\/li><li>reduction in the player&#8217;s stamina due to using a special ability,<\/li><li>regeneration to the player&#8217;s health due to normal passive health regen (yes, even though a <code>subss<\/code> instruction is being used),<\/li><li>regeneration to the player&#8217;s stamina due to normal passive stamina regen, <\/li><li>what appeared to be changes in position for elements on the screen&#8217;s HUD, and<\/li><li>many other unknown changes to known values as well as changes to unknown values.<\/li><\/ul>\n\n\n\n<p>This is a lot of things to filter on. And, don&#8217;t forget, that we&#8217;re of course operating in &#8220;machine-land&#8221;, given that we&#8217;re writing assembly. We need to be real clever in order to cherry pick the kinds of operations we&#8217;re interested in. Many times when we&#8217;re trying to filter out various operations from code we&#8217;re hooking into, we&#8217;re able to discern (most likely) statically determined values stored in registers that indicate the state of the operation. Can we do that with <em>The Witcher 3<\/em>?<\/p>\n\n\n\n<p>To make a long story short, and to answer the question: no. No such thing was possible. Indeed, I must say that the fact I figured out how to successfully filter out all these operations is really a testament to my method and gives me confidence that I&#8217;ll be able to do the same in any kind of software. It also just gives me one of those nice warm feelings.<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Filtering_Out_All_Operations_Unrelated_to_W3AbilityManager\"><\/span>Filtering Out All Operations Unrelated to W3AbilityManager<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>All of the filtering we&#8217;re about to do is done by acting on the values of various bits of data stored on the stack, expect for one particular piece of data: the contents of the <code>r12<\/code> register. Remember, in this &#8220;property unroller&#8221; code, the <code>r12<\/code> register points to the data source for the values being calculated. If we can filter out all operations executed by this code that have nothing to do with a <strong>W3AbilityManager<\/strong> instance, we remove a lot of the &#8220;unknown changes&#8221; I briefly alluded to above.<\/p>\n\n\n\n<p>How do we do that? Well, we know our own <strong>W3AbilityManager<\/strong> instance, but we need to hook into damage being done to enemies as well (since the Apocalypse system includes the Enemy Apocalypse, which does a lot of cool things for us in regards to damage done to enemies such as statistical tracking, etc.). So, we need to be able to determine the <em>type<\/em> of the data in <code>r12<\/code>.<\/p>\n\n\n\n<p>That might sound like a hard thing to do in the scary world of assembly, but fortunately for us, it is rather easy to do in the case of <em>The Witcher 3<\/em>. Let&#8217;s take a look at a snapshot of our own ability manager first:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"915\" height=\"525\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic9.png\" alt=\"Our player's W3AbilityManager and its addresses, including its type identity.\" class=\"wp-image-1490\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic9.png 915w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic9-300x172.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic9-768x441.png 768w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/ApocalypsePic9-480x275.png 480w\" sizes=\"(max-width: 915px) 100vw, 915px\" \/><figcaption>Here&#8217;s my ability manager at the time of trying to develop a filter for only damage applications.<\/figcaption><\/figure><\/div>\n\n\n\n<p>The very first member of this data structure, like other structures in this game, points to essentially a collection of instances of similar data, and essentially acts as an identifier for the data structure&#8217;s type. The address of this type identity, <code>0x7FF676D60F78<\/code>, will never change (well, barring a software update), and we&#8217;ll be using that as this type&#8217;s identity value to match up against. To make things simpler, we&#8217;ll just be looking at the lower 2 bytes of the address: <code>0x0F78<\/code>.<\/p>\n\n\n\n<h4><span class=\"ez-toc-section\" id=\"W3AbilityManager_Filter_Code\"><\/span>W3AbilityManager Filter Code<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n  \/\/ Check if operation is being done on an entity's ability manager first.\n  \/\/ r12 is the source of the values being calculated.\n  cmp r12,0\n  \/\/ If r12 isn't set, this has nothing to do with damage.\n  je initiateApocalypseExit\n  mov rax,[r12]\n  \/\/ Lower 2 bytes of W3AbilityManager's type identity is 0x0F78.\n  cmp ax,0x0F78\n  jne initiateApocalypseExit \n<\/pre>\n\n\n<p>This bit of code will filter out a large, large amount of operations that we are not interested in. But we are by no means out of the woods yet. <\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Filtering_Out_All_Operations_Unrelated_to_Damage_to_Player\"><\/span>Filtering Out All Operations Unrelated to Damage to Player<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>If you recall from the last article, the ability manager structure (which points to the <strong>Vitals <\/strong>structure) is responsible for maintaining not only the character&#8217;s health, but also their stamina, as well as other values. Additionally, we have a number of operations involved here that deal with the <em>regeneration<\/em> of values, something we really don&#8217;t care about!<\/p>\n\n\n\n<p>Figuring out how to separate health loss due to enemy damage from all the other stuff took some hardcore reverse engineering and pattern matching. That basically translates to me doing what I needed to in order to get a particular operation to execute in the game, taking a snapshot of the stack at that point in time, and then comparing it to the stack as it was when the player was being damaged. It took awhile, but we ended up with some very reliable filtering code.<\/p>\n\n\n\n<p>Here is the method in which I filter out all operations not related to the player losing health due to an enemy attack:<\/p>\n\n\n\n<ol><li>First, we see if <code>r12<\/code> is equal to our own player ability manager. If it isn&#8217;t, then nothing is happening to the player. Perhaps it is damage that is being done to an enemy instead; this is covered in its own section below.<\/li><li><code>[rsp+A0]<\/code> is zero when a vital stat amount is changing for Geralt. If it isn&#8217;t zero, then we bail.<\/li><li><code>[rsp+50]<\/code> is zero only when stamina is changing. It is non-zero if health <em>might <\/em>be changing.<\/li><li>Assuming <code>[rsp+50]<\/code> is not zero, then a zero value stored at <code>[rsp+80]<\/code> indicates health is changing.<\/li><li>Finally, we need to see what is being pointed to by <code>[rsp+68]<\/code>. It must point to something, however it <em>cannot<\/em> be pointing to a data structure of the type <strong>CFunction<\/strong>. If it does point to such a function, that means the operation is most likely the result of a recurring regenerative type function, such as the normal restoration of health over time.<\/li><li>If and only if all of the above conditions pass, we can conclude that we are dealing with an operation that is concerned with the reduction of the player&#8217;s health due to an attack from an enemy.<\/li><\/ol>\n\n\n\n<p>Fun little fact: even though the game states that there is no health regeneration on the highest difficulty (I think it does at least), there actually is a very small amount of regeneration (I&#8217;m pretty sure it&#8217;s not from some kind of item I have equipped&#8230;don&#8217;t quote me though). This complicated matters, but it did give us better code in the end, since we need to be able to filter out health regeneration from sources like food or potion, etc.<\/p>\n\n\n\n<p>Anyway, as you have no doubt concluded yourselves, this is all very complicated. Don&#8217;t worry, it gets worse. Rest assured however, what we have in the end is very, very reliable hit detection code for damage being done to the player from the enemy.<\/p>\n\n\n\n<h4><span class=\"ez-toc-section\" id=\"Player_Hit_Detection_Code\"><\/span>Player Hit Detection Code<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n  \/\/ If our ability manager is the data source, then this set to 0 indicates a vital stat amount is\n  \/\/ changing for Geralt.  \n  mov eax,[rsp+A0]\n  cmp eax,0\n  jne verifyCiriDamaged\n  \/\/ Check if Geralt's stamina is changing.\n  \/\/ This is 0 when stamina is changing.\n  mov eax,[rsp+50]\n  cmp eax,0\n  je initiateApocalypseExit\n  \/\/ If stamina is not changing, check if Geralt's health is changing.\n  \/\/ This is 0 when health is changing.\n  mov rax,[rsp+80]\n  cmp eax,0\n  jne initiateApocalypseExit  \n  \/\/ This must point to something, it just can't point to a function.\n  mov rbx,[rsp+68]\n  push rcx\n  lea rcx,[rbx]\n  call checkBadPointer\n  cmp ecx,0\n  pop rcx  \n  jne initiateApocalypseExit  \n  \/\/ If this points to something, it must not be a function. If it is, then the operation is the result\n  \/\/ of a recurring regenerative type function. If it isn't, then this operation is being caused by\n  \/\/ damage from an enemy.\n  mov rax,[rbx]\n  cmp ax,0xFA58\n  jne initiatePlayerApocalypse\n  jmp initiateApocalypseExit\n<\/pre>\n\n\n<p>Please be aware that the offsets used to access the stack do not account for the normal data preservation that takes place in the code that I write. This is done on purpose in order to drive home exactly what we are doing here. The proper offsets are made available in an upcoming section where we&#8217;re discussing the initiation point hook as a whole.<\/p>\n\n\n\n<p>So, we&#8217;re good, right? No. Not at all. All we have discussed is hit detection code for when the player is being hit by an enemy. Don&#8217;t forget: the Apocalypse system has a module for damage done to the player as well as a module for damage done to the enemy by the player. We need to be able to disseminate both cases. Therefore, we need to be able to provide some hit detection logic for when it is enemies receiving the sword stab.<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Determining_When_the_Player_Is_Damaging_an_Enemy\"><\/span>Determining When the Player Is Damaging an Enemy<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>If you&#8217;ll recall, one of the first checks we do during our hit detection code is the determination of whether <code>r12<\/code> points to the player&#8217;s ability manager or not. This occurs after we&#8217;ve determined that <code>r12<\/code> actually points to some type of <strong>W3AbilityManager<\/strong>. You might think that simply knowing that <code>r12<\/code> is both a <strong>W3AbilityManager<\/strong> and not our own ability manager is enough to determine that an enemy has been damaged.<\/p>\n\n\n\n<p>You would be correct, however it is not enough to determine that an enemy has been damaged <em>by the player<\/em>. The Enemy Apocalypse module has an important role to fill, so it is important that only damage coming from the player result in its execution.<\/p>\n\n\n\n<p>Making the determination that the player is the source of the damage is often a difficult thing to do in most games; <em>The Witcher 3<\/em> brings all of that difficult to a new level, somewhat. <\/p>\n\n\n\n<p>In order to detect the player as source of damage, we need to look at various places on the stack. We must try not to base our filtering on too many &#8220;magical values&#8221; that can change at a moments notice. We need to find actual data that is linkable to known instances of data for our player in order to be sure.<\/p>\n\n\n\n<p>Over time I noticed that, while we were able to find such data in the stack that linked back to the player, the exact type of linking data and its location sometimes depended on the type of enemy we were fighting. This is typically a very worrying thing when trying to implement pattern detection, however I&#8217;m reasonably confident that the procedure I&#8217;ve come up is going to work throughout the playthrough.<\/p>\n\n\n\n<p><em>If it ends up needing some updates, pay close attention to my <a href=\"https:\/\/github.com\/BadEcho\/core\" target=\"_blank\" rel=\"noreferrer noopener\">source control<\/a>!<\/em><\/p>\n\n\n\n<p>When a non-player entity is being targeted, we determine that the player is responsible using the following procedure:<\/p>\n\n\n\n<ol><li>The address stored in <code>[rsp+68]<\/code> will point to the player&#8217;s ability manager when the player is responsible for damage being done to <em>most<\/em> enemies. If it doesn&#8217;t, we go to the next step.<\/li><li>The address stored in <code>[rsp+410]<\/code> will point to the player&#8217;s ability manager when the player is responsible for damage being done to <em>some<\/em> enemies. If it doesn&#8217;t, we go to the next step.<\/li><li>The address stored in <code>[rsp+8]<\/code> will point to the player&#8217;s ability manager when the player is responsible for damage being done to <em>some<\/em> enemies. If it doesn&#8217;t, we go to the next step.<\/li><li>We take another look at the address stored at <code>[rsp+410]<\/code> and see if it is pointing to our character&#8217;s root structure. For a very select few (but important, i.e. the big monsters in the game) creatures, this will indicate that our player is responsible for the damage being done.<\/li><li>If none of the above conditions pass, then the player is not responsible for the damage being done to an enemy.<\/li><\/ol>\n\n\n\n<p>After much testing, I&#8217;m very satisfied with this hit detection logic. <\/p>\n\n\n\n<h4><span class=\"ez-toc-section\" id=\"Enemy_Hit_by_Player_Detection_Code\"><\/span>Enemy Hit by Player Detection Code<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n  \/\/ This will point to our ability manager for MOST enemies when we're responsible for the damage.\n  mov rbx,[rsp+68]\n  cmp [rax],rbx\n  je initiateEnemyApocalypse\n  \/\/ This will point to our ability manager for SOME enemies when we're responsible for the damage.\n  mov rbx,[rsp+410]\n  cmp [rax],rbx\n  je initiateEnemyApocalypse\n  \/\/ This will point to our ability manager for SOME enemies when we're responsible for the damage.\n  mov rbx,[rsp+8]\n  cmp [rax],rbx\n  je initiateEnemyApocalypse\n  \/\/ This will point to our root structure for a select few enemies when we're responsible for the\n  \/\/ damage.\n  mov rax,player\n  mov rbx,[rsp+410]\n  cmp [rax],rbx\n  je initiateEnemyApocalypse\n  jmp initiateApocalypseExit\n<\/pre>\n\n\n<p>Whew boy. This is some intense hit detection logic! This is all <em>very necessary<\/em>; it is amazing how many different kinds of values are being calculated by this little bit of code. I am quite happy with myself for figuring out how to separate the wheat from the chaff.<\/p>\n\n\n\n<p>So, we&#8217;re good to go right? Nope. If we&#8217;re just talking about playing Geralt, then yes, we are good to go. However, as you may know, at certain times during this game you are playing from the perspective of Ciri (Geralt&#8217;s ward). And unfortunately, that turns everything a bit on its head as far as hit detection goes.<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"On_the_Matter_of_Ciri%E2%80%99s_Hit_Detection\"><\/span>On the Matter of Ciri&#8217;s Hit Detection<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Very annoyingly, not long after the first sequence where we play as Ciri started, I noticed that the hit detection for when the player is getting damaged by enemies was no longer sufficient. Simply put, it would incorrectly exclude operations that were genuinely concerned with enemies damaging Ciri&#8217;s health.<\/p>\n\n\n\n<p>Quite confusingly, while we were able to make use of the same data points that we use with Geralt, the values of the data points had to be exactly the opposite of what they needed to be when Geralt was getting smacked. Yes, that makes my head hurt as well. Here&#8217;s the process for Ciri&#8217;s hit detection:<\/p>\n\n\n\n<ol><li>If you can recall, we look at <code>[rsp+A0]<\/code> to see if the change that is occurring involves one of Geralt&#8217;s vital stats. If its value is zero, then that means a vital stat is changing. We previously concluded that a vital stat is <em>not<\/em> changing if it is not zero. While true, it also signals to us that a vital stat belonging to Ciri <em>might be changing instead<\/em>. So, we use this particular point in memory to determine whether we&#8217;re dealing with Ciri vs Geralt here as far as hit detection goes.<\/li><li>If <code>[rsp+A0]<\/code> is 0 (and therefore indicative of a change not involving one of Geralt&#8217;s vital stats), then we proceed to check if perhaps one of Ciri&#8217;s is changing. We look at <code>[rsp+50]<\/code> next, just like we do for Geralt. Instead of a value of zero being indicative of stamina changing (like it is with Geralt), it&#8217;s actually a non-zero value that indicates a (what I assume to be) stamina change as far Ciri is concerned. So, if <code>[rsp+50]<\/code> is zero, we continue.<\/li><li>We then take a look at <code>[rsp+80]<\/code>, just like we do for Geralt. And, once again, the significance of the value is opposite to its significance when we&#8217;re detecting hits on Geralt. So, in the case of Ciri, this value must be <em>not be zero<\/em>. <\/li><li>Unlike Geralt, we don&#8217;t need to check for the presence of a recurring regenerative function. One of the other steps must weed it out.<\/li><\/ol>\n\n\n\n<p>Yes, very confusing, but the end result is a very reliable hit detection algorithm for both Geralt and Ciri!<\/p>\n\n\n\n<h4><span class=\"ez-toc-section\" id=\"Player_Hit_Detection_Code_(Ciri)\"><\/span>Player Hit Detection Code (Ciri)<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n  \/\/ For Ciri, this is not 0 (unlike Geralt) when (assumingly) stamina is changing.\n  \/\/ If it is 0, then Ciri may be losing health.\n  mov eax,[rsp+50]\n  cmp eax,0\n  jne initiateApocalypseExit\n  \/\/ For Ciri, if stamina isn't changing, then this is not 0 when losing health.\n  \/\/ No check for a recurring function is required for Ciri.\n  mov rax,[rsp+80]\n  cmp eax,0\n  je initiateApocalypseExit \n<\/pre>\n\n\n<p>Once again, offsets are not adjusted for all our data preservation that gets pushed to the stack. Proper offsets will be provided to the reader below.<\/p>\n\n\n\n<p>And&#8230;yes&#8230;that&#8217;s it! That&#8217;s our hit detection code. I&#8217;ve tested it on stream and it is very reliable, and I&#8217;m super psyched I was able to do it. Seriously, if we can do it for this function, which is called to process so many different types of calculations, we can do it for anything, in any game.<\/p>\n\n\n\n<h2><span class=\"ez-toc-section\" id=\"On_the_Matter_of_Ciri%E2%80%99s_Coordinates\"><\/span>On the Matter of Ciri&#8217;s Coordinates<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>This may seem a bit off-topic, however anomalies in regards to Ciri&#8217;s coordinates were brought to light during our implementation of the Apocalypse system. As you may know, one of the parameters for the Player Apocalypse is the address to the player&#8217;s location structure, aligned at the X coordinate. It is required, and if the location coordinates are not known, well we&#8217;re just going to get a big ol&#8217; crash, aren&#8217;t we?<\/p>\n\n\n\n<p>And that&#8217;s what happened with Ciri: some big ol&#8217; crashes. It happened because the hook we created for finding Geralt&#8217;s coordinates in the <a href=\"https:\/\/badecho.com\/index.php\/2021\/04\/04\/hacking-witcher-part-1\/\" target=\"_blank\" rel=\"noreferrer noopener\">first article<\/a> did not appear to be executing when we were controlling Ciri. <\/p>\n\n\n\n<p>What a pain! And how strange &#8212; in most every game I&#8217;ve hacked that featured multiple controllable characters throughout a story, I would observe that hooks into critical data structures for one character would almost always get reused when controlling another character. Clearly Ciri is being treated a bit differently from Geralt &#8212; hopefully not too differently.<\/p>\n\n\n\n<p>Luckily for us (since finding the coordinates from scratch is a bit of a pain), Ciri&#8217;s <em>immediate<\/em> coordinates were still being found through the hook into the immediate character physics wrapper:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"462\" height=\"60\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/CirisCoordinates1.png\" alt=\"Shows Ciri's still functioning Immediate coordinate values.\" class=\"wp-image-1492\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/CirisCoordinates1.png 462w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/CirisCoordinates1-300x39.png 300w\" sizes=\"(max-width: 462px) 100vw, 462px\" \/><figcaption>Ciri&#8217;s immediate coordinates are still present, so we still have a valid physics wrapper. We&#8217;ll use these to find her actual coordinates.<\/figcaption><\/figure><\/div>\n\n\n\n<p>Since these are <em>roughly<\/em> equivalent to the actual coordinates, it didn&#8217;t take long to find her coordinates in memory. I immediately then checked out what code was accessing them.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"811\" height=\"556\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/CirisCoordinates2.png\" alt=\"Shows the code accessing Ciri's actual coordinates\" class=\"wp-image-1493\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/CirisCoordinates2.png 811w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/CirisCoordinates2-300x206.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/CirisCoordinates2-768x527.png 768w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/CirisCoordinates2-480x329.png 480w\" sizes=\"(max-width: 811px) 100vw, 811px\" \/><figcaption>Here are the instructions accessing Ciri&#8217;s actual coordinates &#8212; only the one we used to find Geralt&#8217;s is missing, interestingly enough.<\/figcaption><\/figure><\/div>\n\n\n\n<p>I was disappointed to see that all the instructions I saw accessing Geralt&#8217;s coordinates were present here &#8212; except for the one we decided to hook into! This disappointment is doubled in magnitude when we consider that the reason we hooked into that particular code was because it was the only one code accessing the coordinates that was constantly executing. All of the other functions, and indeed all of the ones in the above image, only execute when the character moves.<\/p>\n\n\n\n<p>We want to <em>always<\/em> know what the player&#8217;s coordinates are, as soon as possible, before any movement. There are many reasons for this (I&#8217;ve provided many examples in the past) &#8212; so what do we do? We do what the game does: we find the data relationally, using the character&#8217;s root structure as the starting point for our own search.<\/p>\n\n\n\n<p>Technically speaking (and with, I&#8217;ll admit, quite a few assumptions being made) if we have access to a character&#8217;s root data structure, we should be able to be find any and all data structures pertaining to that character. That requires, however, doing some reverse engineering of the contents of these structures and charting the paths to and from a particular piece of data we&#8217;re interested in.<\/p>\n\n\n\n<p>We already found the root structure for the character in the previous article, so we only needed to figure out how to get from there to the character&#8217;s location structure. We had no idea how to do this, so I got some inspiration by looking at how the game was charting its own path to the location structure.<\/p>\n\n\n\n<p>After a bit of poking around (of which you can review on your own from recorded footage of my stream), I was overjoyed to be able to find the path one must take in order to find a source of truth location structure from a character&#8217;s root structure.<\/p>\n\n\n\n<p>The path to grab ahold of the player&#8217;s location structure from the root structure is illustrated in this updated code for our hook that grabs the player&#8217;s root structure (the separate player location hook we previously had is no longer needed).<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Updated_Player_Root_Structure_Hook_With_Resolved_Location\"><\/span>Updated Player Root Structure Hook With Resolved Location<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Gets the player's root structure as well as resolving the source of truth location coordinate\n\/\/ structure found on it.\ndefine(omniPlayerHook,&quot;witcher3.exe&quot;+AB139)\n\nassert(omniPlayerHook,48 8B 01 48 8D 54 24 60)\nalloc(getPlayer,$1000,omniPlayerHook)\nalloc(player,8)\nalloc(playerLocation,8)\n\nregistersymbol(omniPlayerHook)\nregistersymbol(player)\nregistersymbol(playerLocation)\n\ngetPlayer:\n  pushf\n  push rax\n  push rbx\n  push rcx\n  mov rax,[rcx]\n  cmp ax,0xC418\n  jne getPlayerExit\n  mov rax,player\n  mov [rax],rcx\n  \/\/ Grab the CMovingPhysicalAgentComponent.\n  mov rbx,[rcx+0x218]\n  \/\/ Grab the CMRPhysicalCharacter.\n  mov rcx,[rbx+0x1648]\n  \/\/ Grab the source CPhysicsCharacterWrapper.\n  mov rbx,[rcx+0x10]\n  \/\/ Grab the location coordinates holder.\n  mov rcx,[rbx+0x78]\n  mov rax,playerLocation\n  add rcx,8\n  mov [rax],rcx\ngetPlayerExit:\n  pop rcx\n  pop rbx\n  pop rax\ngetPlayerOriginalCode:\n  popf\n  mov rax,[rcx]\n  lea rdx,[rsp+60]\n  jmp getPlayerReturn\n\nomniPlayerHook:\n  jmp getPlayer\n  nop 3\ngetPlayerReturn:\n<\/pre>\n\n\n<p>Being able to retrieve character data directly from a root structure is a superior method in acquiring this kind of data. A big win!<\/p>\n\n\n\n<h2><span class=\"ez-toc-section\" id=\"Adding_Apocalypse_Support_for_Coordinate_Doubles\"><\/span>Adding Apocalypse Support for Coordinate Doubles<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>In primarily <a href=\"https:\/\/badecho.com\/index.php\/2021\/04\/04\/hacking-witcher-part-1\/\" target=\"_blank\" rel=\"noreferrer noopener\">the previous article<\/a> as well this article, I&#8217;ve spoken about how this game uses <strong>double<\/strong> as the value type for its source of truth coordinates. Every other game I&#8217;ve hacked so far has used <strong>float<\/strong>, save for <em>Subnautica<\/em>, which used doubles, but only for while the player was on land (very odd, but whatever).<\/p>\n\n\n\n<p>If one consults the <a href=\"https:\/\/badecho.com\/index.php\/2020\/10\/19\/apocalypse-system\/\" target=\"_blank\" rel=\"noreferrer noopener\">Apocalypse system design article<\/a>, one will become very familiar with one of the standout features of the system: the <strong>teleportitis<\/strong> effect. This effect randomly teleports the character somewhere following some damage being received. The way we effectuate changes to the player&#8217;s location is by directly writing to the place in memory in which the coordinates live.<\/p>\n\n\n\n<p>Well, up until now, we&#8217;ve been able to do this the same way for every game, since every game has used floating points to hold its coordinates. Writing directly to such a structure truly seemed to be quite &#8220;game-neutral&#8221;, given that every game I&#8217;ve encountered has had the exact same memory footprint as far as the three well known axes (X, Y, and Z) were concerned.<\/p>\n\n\n\n<p>Well, this game uses doubles. That means the memory footprint has changed. That also means, then, that we have to do something I don&#8217;t have to do much, if ever, when implementing an Omnified system into a game: we need to add some additional functionality to the Omnified system in order for it to support said game.<\/p>\n\n\n\n<p>In particular, we need to be able to support exporting teleportitis affected coordinate values to coordinate location structures that use doubles for each axis value. Doing so required the addition of a new external parameter: <code>coordinatesAreDoubles<\/code>, as well as modification of the teleportitis effect code found under the <code>commitTeleportitis<\/code> label in the Omnified framework assembly code file.<\/p>\n\n\n\n<p>Here now is the updated teleportitis effect code with double coordinate support added into it:<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Updated_Teleportitis_Effect_Code_in_Omnified_Framework\"><\/span>Updated Teleportitis Effect Code in Omnified Framework<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\ncommitTeleportitis:\n  \/\/ Some games will disable modifications being made to the player's coordinates\n  \/\/ during certain animations such as weapon attacks or getting knocked back.\n  \/\/ This code needs to be hooked into and temporarily disabled in order for \n  \/\/ teleportitis to work. This can be done by checking the &quot;teleported&quot; symbol \n  \/\/ and preventing those coordinates from being reset. That code will then \n  \/\/ need to set this symbol to 0. In most games I've hacked, this is not \n  \/\/ required. In fact, only one: Dark Souls I.\n  mov [teleported],1\n  \/\/ Load the player coordinates address parameter.\n  mov rbx,[rsp+48]\n  \/\/ Load the parameters for generating the random displacement value to be \n  \/\/ applied to the X coordinate.\n  push [teleportitisResultLower]\n  push [teleportitisResultUpper]\n  mov rax,playerApocalypseRandomState\n  push rax\n  call generateRandomNumber\n  \/\/ The random number is an integer and will need to be converted to a float.\n  mov [teleportitisResult],eax\n  cvtsi2ss xmm1,[teleportitisResult]\n  \/\/ The random number is divided by the following divisor to bring it into the\n  \/\/ expected range (0-10) along with some decimal precision (3 decimal places).\n  divss xmm1,[teleportitisDivisor]\n  \/\/ We cannot generate random negative integers, we instead shift what we have \n  \/\/ here by a negative amount. The range 0 to 10 becomes -5 to 5.\n  subss xmm1,[teleportitisShifter]\n  \/\/ We finally take what we have and then multiply it by the displacement \n  \/\/ multiplier to get the final displacement value to apply to the player's \n  \/\/ X coordinate.\n  mulss xmm1,[teleportitisDisplacementX]\n  \/\/ We then take the player's current X coordinate from memory and add the\n  \/\/ displacement value to it.\n  cmp [coordinatesAreDoubles],1\n  je loadXAsDouble\n  movss xmm2,[rbx]\n  jmp addChangeToX\nloadXAsDouble:\n  cvtsd2ss xmm2,[rbx]\naddChangeToX:\n  addss xmm2,xmm1\n  \/\/ The updated X coordinate is committed back into the memory, which will \n  \/\/ move the player.\n  cmp [coordinatesAreDoubles],1\n  je commitXAsDouble\n  movss [rbx],xmm2\n  jmp teleportY\ncommitXAsDouble:\n  cvtss2sd xmm1,xmm2\n  movsd [rbx],xmm1\nteleportY:\n  \/\/ Load the parameters for generating the random displacement value to be \n  \/\/ applied to the Y coordinate. \n  push [teleportitisResultLower]\n  push [teleportitisResultUpper]\n  mov rax,playerApocalypseRandomState\n  push rax\n  call generateRandomNumber\n  mov [teleportitisResult],eax\n  cvtsi2ss xmm1,[teleportitisResult]\n  divss xmm1,[teleportitisDivisor]\n  \/\/ If the Y-axis is not the vertical axis, then we we don't need to check \n  \/\/ whether vertical displacement is enabled.\n  cmp [yIsVertical],1\n  jne skipYSkipCheck\n  \/\/ If negative vertical displacement is not enabled we do not want to shift it,\n  \/\/ this causes the random value to remain in the range of 0 to 10.\n  cmp [negativeVerticalDisplacementEnabled],1\n  jne skipNegativeVerticalYDisplacement\nskipYSkipCheck:\n  subss xmm1,[teleportitisShifter]\nskipNegativeVerticalYDisplacement:\n  mulss xmm1,[teleportitisDisplacementX]\n  \/\/ The vertical displacement value is logged and displayed to viewers as \n  \/\/ changes to are often the most consequential. We make sure the Y-axis is \n  \/\/ the vertical one before logging it.\n  cmp [yIsVertical],1\n  jne skipLastYVerticalDisplacement\n  movss [lastVerticalDisplacement],xmm1\nskipLastYVerticalDisplacement:\n  \/\/ We then take the player's current Y coordinate from memory and add the\n  \/\/ displacement value to it.\n  cmp [coordinatesAreDoubles],1\n  je loadYAsDouble\n  movss xmm2,[rbx+4]\n  jmp addChangeToY\nloadYAsDouble:\n  cvtsd2ss xmm2,[rbx+8]\naddChangeToY:\n  addss xmm2,xmm1\n  \/\/ The updated Y coordinate is commited back into the memory, which will \n  \/\/ move the player.\n  cmp [coordinatesAreDoubles],1\n  je commitYAsDouble\n  movss [rbx+4],xmm2\n  jmp teleportZ\ncommitYAsDouble:\n  cvtss2sd xmm1,xmm2  \n  movsd [rbx+8],xmm1\nteleportZ:\n  \/\/ Load the parameters for generating the random displacement value to be \n  \/\/ applied to the Z coordinate. \n  push [teleportitisResultLower]\n  push [teleportitisResultUpper]\n  mov rax,playerApocalypseRandomState\n  push rax\n  call generateRandomNumber\n  mov [teleportitisResult],eax\n  cvtsi2ss xmm1,[teleportitisResult]\n  divss xmm1,[teleportitisDivisor]\n  \/\/ Like the Y-axis, the Z-axis can sometimes be the vertical axis. So checks \n  \/\/ similar to the ones made in the Y coordinate displacement code are made.\n  cmp [yIsVertical],0\n  jne skipZSkipCheck\n  cmp [negativeVerticalDisplacementEnabled],1\n  jne skipNegativeVerticalZDisplacement\nskipZSkipCheck:\n  subss xmm1,[teleportitisShifter]\nskipNegativeVerticalZDisplacement:\n  mulss xmm1,[teleportitisDisplacementX]\n  cmp [yIsVertical],0\n  jne skipLastZVerticalDisplacement\n  movss [lastVerticalDisplacement],xmm1\nskipLastZVerticalDisplacement:\n  \/\/ We then take the player's current Z coordinate from memory and add the\n  \/\/ displacement value to it.\n  cmp [coordinatesAreDoubles],1\n  je loadZAsDouble\n  movss xmm2,[rbx+8]  \n  jmp addChangeToZ\nloadZAsDouble:\n  cvtsd2ss xmm2,[rbx+10]\naddChangeToZ:\n  addss xmm2,xmm1\n  \/\/ The updated Z coordinate is commited back into the memory, which will \n  \/\/ move the player.\n  cmp [coordinatesAreDoubles],1\n  je commitZAsDouble\n  movss [rbx+8],xmm2\n  jmp updateEnemyDamageStats\ncommitZAsDouble:\n  cvtss2sd xmm1,xmm2\n  movsd [rbx+10],xmm1  \n  jmp updateEnemyDamageStats\n<\/pre>\n\n\n<p>Just want to state for the record that the changes worked first try! I don&#8217;t care how mundane the matter is: that isn&#8217;t easy when we&#8217;re writing raw assembly!! Yes I know I&#8217;m bragging, forgive me.<\/p>\n\n\n\n<h2><span class=\"ez-toc-section\" id=\"Writing_the_Apocalypse_Initiation_Hook\"><\/span>Writing the Apocalypse Initiation Hook<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Time to make this game freaking great by adding some Apocalypse magic to it. We&#8217;re going to hook directly into the code we identified earlier as our damage application code. Here&#8217;s a look at the initial template for our hook:<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Apocalypse_Initiation_Hook_%E2%80%93_Template\"><\/span>Apocalypse Initiation Hook &#8211; Template<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Initiates the Apocalypse system.\n\/\/ [rsp+40] | {rsp+62}: Damage amount.\n\/\/ xmm0: Player's current health.\n\/\/ r12: Data source for values being calculated.\ndefine(omnifyApocalypseHook,&quot;witcher3.exe&quot;+16529F4)\n\nassert(omnifyApocalypseHook,F3 0F 5C 44 24 40)\nalloc(initiateApocalypse,$1000,omnifyApocalypseHook)\n\nregistersymbol(omnifyApocalypseHook)\n\ninitiateApocalypse:\n  \ninitiateApocalypseOriginalCode:\n  subss xmm0,[rsp+40]\n  jmp initiateApocalypseReturn\nomnifyApocalypseHook:\n  jmp initiateApocalypse\n  nop \ninitiateApocalypseReturn:\n<\/pre>\n\n\n<p>What we&#8217;re going to have to do is implement that hit detection code talked about at length in the previous sections and then execute the primary functions of the Apocalypse system, which will be either <code>executePlayerApocalypse<\/code> or <code>executeEnemyApocalypse<\/code> depending on who or what is getting smacked.<\/p>\n\n\n\n<p>Because of the hit detection required, we need to do a little bit more work here than normal prior to calling the Apocalypse system. Because I discussed in detail what is involved for proper hit detection, I won&#8217;t rehash that here. Before stepping into the code however, we need to account for all the data that we need to push to the stack in order to preserve it.<\/p>\n\n\n\n<p>Let&#8217;s go over what we&#8217;re going to need to push to the stack to ensure data integrity:<\/p>\n\n\n\n<ol><li>As always, we want to back up all conditional flags. That&#8217;s going to eat up <strong>2 bytes<\/strong>.<\/li><li>Next, we&#8217;ll need a least one SSE register to hold floating point values to do whatever we need to do with them. We&#8217;ll be backing up <code>xmm1<\/code>, and that&#8217;ll eat up <strong>16 bytes<\/strong>.<\/li><li>Finally, we&#8217;ll want to back up <code>rax<\/code> and <code>rbx<\/code> since the Apocalypse system uses those registers as return values. That&#8217;s two registers at <strong>8 bytes<\/strong> each for a total of <strong>16 bytes<\/strong>.<\/li><\/ol>\n\n\n\n<p>Adding all of that up, we&#8217;re given a total of <strong>34 bytes<\/strong>, or <code>0x22<\/code> bytes when we&#8217;re speaking hex talk (which is, you know, what we speak around here)!<\/p>\n\n\n\n<p>As always, for more information in regards to the requirements involved when writing Apocalypse initiation points, please consult the relevant sections in the Apocalypse overview article on the <a href=\"https:\/\/badecho.com\/index.php\/2020\/10\/19\/apocalypse-system\/#player-apocalypse-api\" target=\"_blank\" rel=\"noreferrer noopener\">Player Apocalypse API<\/a> and the <a href=\"https:\/\/badecho.com\/index.php\/2020\/10\/19\/apocalypse-system\/#enemy-apocalypse-api\" target=\"_blank\" rel=\"noreferrer noopener\">Enemy Apocalypse API<\/a>. Hope that answers everything!<\/p>\n\n\n\n<p>To start everything off, let&#8217;s back up all the data we need to and implement our girthy hit detection system.<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Apocalypse_Initiation_Hook_%E2%80%93_First_Steps\"><\/span>Apocalypse Initiation Hook &#8211; First Steps<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\ninitiateApocalypse:\n  pushf\n  \/\/ Ensure that player ability manager pointer has been initialized.\n  push rax\n  mov rax,playerAbilityManager\n  cmp [rax],0\n  pop rax\n  je initiateApocalypseOriginalCode\n  sub rsp,10\n  movdqu [rsp],xmm1\n  push rax\n  push rbx\n  \/\/ Check if operation is being done on an entity's ability manager first.\n  \/\/ r12 is the source of the values being calculated.\n  cmp r12,0\n  \/\/ If r12 isn't set, this has nothing to do with damage.\n  je initiateApocalypseExit\n  mov rax,[r12]\n  \/\/ Lower 2 bytes of W3AbilityManager's type identity is 0x0F78.\n  cmp ax,0x0F78\n  jne initiateApocalypseExit  \n  \/\/ Check if player is damaging an enemy. \n  \/\/ If we're damaging an enemy, r12 will not point to our own ability manager.\n  mov rax,playerAbilityManager\n  cmp [rax],r12\n  je verifyPlayerDamaged\n  \/\/ This will point to our ability manager for MOST enemies when we're responsible for the damage.\n  mov rbx,[rsp+8A]\n  cmp [rax],rbx\n  je initiateEnemyApocalypse\n  \/\/ This will point to our ability manager for SOME enemies when we're responsible for the damage.\n  mov rbx,[rsp+432]\n  cmp [rax],rbx\n  je initiateEnemyApocalypse\n  \/\/ This will point to our ability manager for SOME enemies when we're responsible for the damage.\n  mov rbx,[rsp+2A]\n  cmp [rax],rbx\n  je initiateEnemyApocalypse  \n  \/\/ This will point to our root structure for a select few enemies when we're responsible for the\n  \/\/ damage. \n  mov rax,player\n  mov rbx,[rsp+432]\n  cmp [rax],rbx\n  je initiateEnemyApocalypse\n  jmp initiateApocalypseExit  \nverifyPlayerDamaged:\n  \/\/ If our ability manager is the data source, then this set to 0 indicates a vital stat amount is\n  \/\/ changing for Geralt.  \n  mov eax,[rsp+C2]\n  cmp eax,0\n  jne verifyCiriDamaged\n  \/\/ Check if Geralt's stamina is changing.\n  \/\/ This is 0 when stamina is changing.\n  mov eax,[rsp+72]\n  cmp eax,0\n  je initiateApocalypseExit\n  \/\/ If stamina is not changing, check if Geralt's health is changing.\n  \/\/ This is 0 when health is changing.\n  mov rax,[rsp+A2]\n  cmp eax,0\n  jne initiateApocalypseExit  \n  \/\/ This must point to something, it just can't point to a function.\n  mov rbx,[rsp+8A]\n  push rcx\n  lea rcx,[rbx]\n  call checkBadPointer\n  cmp ecx,0\n  pop rcx  \n  jne initiateApocalypseExit  \n  \/\/ If this points to something, it must not be a function. If it is, then the operation is the\n  \/\/ result of a recurring regenerative type function. If it isn't, then this operation is being\n  \/\/ caused by damage from an enemy.\n  mov rax,[rbx]\n  cmp ax,0xFA58\n  jne initiatePlayerApocalypse\n  jmp initiateApocalypseExit  \nverifyCiriDamaged:\n  \/\/ For Ciri, this is not 0 (unlike Geralt) when (assumingly) stamina is changing.\n  \/\/ If it is 0, then Ciri may be losing health.\n  mov eax,[rsp+72]\n  cmp eax,0\n  jne initiateApocalypseExit\n  \/\/ For Ciri, if stamina isn't changing, then this is not 0 when losing health.\n  \/\/ No check for a recurring function is required for Ciri.\n  mov rax,[rsp+A2]\n  cmp eax,0\n  je initiateApocalypseExit  \n<\/pre>\n\n\n<p>Oh yeah. That hit detection code is no joke. But it works! It&#8217;s fabulous! At least until I run into something that throws it all to crap. But I&#8217;m sure that won&#8217;t happen (<em>knock on wood furiously<\/em>).<\/p>\n\n\n\n<p>In the above code, execution is directed accordingly based on whether the player is being damaged, whether an enemy is being damaged by a player, and whether something else is happening. If the player is being damaged, the Player Apocalypse needs to be called. Let&#8217;s implement that next.<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Apocalypse_Initiation_Hook_%E2%80%93_Player_Apocalypse\"><\/span>Apocalypse Initiation Hook &#8211; Player Apocalypse<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\ninitiatePlayerApocalypse:\n  \/\/ Push the damage amount parameter.\n  movss xmm1,[rsp+62]\n  sub rsp,8\n  movd [rsp],xmm1\n  \/\/ Push the player's current working health value.\n  sub rsp,8\n  movd [rsp],xmm0\n  \/\/ Push the player's maximum health value.\n  mov rax,playerVitals\n  mov rbx,[rax]\n  movss xmm1,[rbx+4]\n  sub rsp,8\n  movd [rsp],xmm1\n  \/\/ Align the player's location struct to the X coordinate and push it.\n  mov rax,playerLocation\n  mov rbx,[rax]\n  lea rax,[rbx+1B8]\n  push rax\n  call executePlayerApocalypse\n  jmp initiateApocalypseUpdateDamage\n<\/pre>\n\n\n<p>Ah nice and easy. Once this code is done executing, we&#8217;ll have an updated damage amount in <code>rax<\/code> and a potentially updated working health value in <code>rbx<\/code>. These return values will then get processed.<\/p>\n\n\n\n<p>But before we get to that, let&#8217;s check out what our call to the Enemy Apocalypse looks like.<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Apocalypse_Initiation_Hook_%E2%80%93_Enemy_Apocalypse\"><\/span>Apocalypse Initiation Hook &#8211; Enemy Apocalypse<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\ninitiateEnemyApocalypse:  \n  \/\/ Push the damage amount parameter.\n  movss xmm1,[rsp+62]\n  sub rsp,8\n  movd [rsp],xmm1\n  \/\/ Push the target's current working health value.\n  sub rsp,8\n  movd [rsp],xmm0\n  call executeEnemyApocalypse\n<\/pre>\n\n\n<p>As always, the Enemy Apocalypse initiation code is a bit simpler than what we have to do for the player, given the fewer number of parameters.<\/p>\n\n\n\n<p>Like the Player Apocalypse code, we end up having return values saved in the <code>rax<\/code> and <code>rbx<\/code> registers. We need to process these return values and update the places in memory that the game code is going to be looking at in order to do its damage application. After that, we&#8217;ll want to wrap everything up and restore the stack and any registers we used to be what they were before we hand control back to the game.<\/p>\n\n\n\n<p>Let&#8217;s write that bit of code up now.<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Apocalypse_Initiation_Hook_%E2%80%93_Return_Value_Processing_and_Cleanup\"><\/span>Apocalypse Initiation Hook &#8211; Return Value Processing and Cleanup<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\ninitiateApocalypseUpdateDamage:\n  \/\/ Commit updated damage and working health.\n  mov [rsp+62],eax\n  movd xmm0,ebx\ninitiateApocalypseExit:\n  pop rbx\n  pop rax\n  movdqu xmm1,[rsp]\n  add rsp,10\n<\/pre>\n\n\n<p>That&#8217;s our Apocalypse system implementation for <em>The Witcher 3<\/em> folks. Before we can call it a day, however, there are a few Apocalypse system external parameters we need to set.<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Apocalypse_Initiation_Hook_%E2%80%93_External_Parameters\"><\/span>Apocalypse Initiation Hook &#8211; External Parameters<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\ncoordinatesAreDoubles:\n  dd 1\n\nnegativeVerticalDisplacementEnabled:\n  dd 0\n\nyIsVertical:\n  dd 0\n<\/pre>\n\n\n<p>In <em>The Witcher 3<\/em>, the Y axis is not the vertical axis; rather, the Z axis is. We&#8217;re also disabling negative vertical displacement because teleporting Geralt underneath the Earth just causes him to fall until he&#8217;s forced to fast travel; no death ever occurs. And, if there&#8217;s no death involved: I&#8217;m not interested! Finally, the coordinates used in this game are double value types, not floats.<\/p>\n\n\n\n<h2><span class=\"ez-toc-section\" id=\"Wrapping_Up\"><\/span>Wrapping Up<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Well that was a lot of interesting work that we attacked very patiently and methodically on stream. In the end, we have the awesome Apocalypse system hooked into <em>The Witcher 3<\/em>. I present to you now the complete code required to add Apocalypse system support to the game:<\/p>\n\n\n\n<h3><span class=\"ez-toc-section\" id=\"Apocalypse_Initiation_Hook_%E2%80%93_Complete\"><\/span>Apocalypse Initiation Hook &#8211; Complete<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Initiates the Apocalypse system.\n\/\/ [rsp+40] | {rsp+62}: Damage amount.\n\/\/ xmm0: Player's current health.\n\/\/ r12: Data source for values being calculated.\n\/\/ Conditions\n\/\/ ----------\n\/\/ If player is being targeted:\n\/\/\n\/\/ [rsp+A0] | {rsp+C2}: Value is 0 if a vital stat amount is changing for Geralt.\n\/\/ A value of 0 means either a non-vital stat is changing or that Ciri is losing a vital stat amount. Confusing, I know.\n\/\/ [rsp+50] | {rsp+72}: Value is 0 when Geralt's stamina is changing. Value is 0 when Ciri might be losing health.\n\/\/ [rsp+80] | {rsp+A2}: Value is 0 when Geralt's health is changing (assuming [rsp+50] is not 0).\n\/\/ Value is not 0 when Ciri is losing health (assuming [rsp+50] is 0). Yes. Confusing lol.\n\/\/ [rsp+68] | {rsp+8A}: If Geralt's health is changing, we must ensure that this points to some kind of data, but \n\/\/ that it does not point to data of type CFunction. If it does, then the operation is most likely a regenerative \n\/\/ one. This does not apply to Ciri for some reason.\n\/\/\n\/\/ If non-player is being targeted:\n\/\/\n\/\/ [rsp+410] | {rsp+432}: Set to player's ability manager when player is damaging SOME enemies.\n\/\/ For A VERY FEW number of enemies, this will be set to the player's root structure.\n\/\/ [rsp+8] | {rsp+2A}: Set to player's ability manager when player is damaging SOME enemies.\n\/\/ [rsp+68] | {rsp+8A}: Set to player's ability manager when player is damaging MOST enemies.\ndefine(omnifyApocalypseHook,&quot;witcher3.exe&quot;+16529F4)\n\nassert(omnifyApocalypseHook,F3 0F 5C 44 24 40)\nalloc(initiateApocalypse,$1000,omnifyApocalypseHook)\n\nregistersymbol(omnifyApocalypseHook)\n\ninitiateApocalypse:\n  pushf\n  \/\/ Ensure that player ability manager pointer has been initialized.\n  push rax\n  mov rax,playerAbilityManager\n  cmp [rax],0\n  pop rax\n  je initiateApocalypseOriginalCode\n  sub rsp,10\n  movdqu [rsp],xmm1\n  push rax\n  push rbx\n  \/\/ Check if operation is being done on an entity's ability manager first.\n  \/\/ r12 is the source of the values being calculated.\n  cmp r12,0\n  \/\/ If r12 isn't set, this has nothing to do with damage.\n  je initiateApocalypseExit\n  mov rax,[r12]\n  \/\/ Lower 2 bytes of W3AbilityManager's type identity is 0x0F78.\n  cmp ax,0x0F78\n  jne initiateApocalypseExit  \n  \/\/ Check if player is damaging an enemy. \n  \/\/ If we're damaging an enemy, r12 will not point to our own ability manager.\n  mov rax,playerAbilityManager\n  cmp [rax],r12\n  je verifyPlayerDamaged\n  \/\/ This will point to our ability manager for MOST enemies when we're responsible for the damage.\n  mov rbx,[rsp+8A]\n  cmp [rax],rbx\n  je initiateEnemyApocalypse\n  \/\/ This will point to our ability manager for SOME enemies when we're responsible for the damage.\n  mov rbx,[rsp+432]\n  cmp [rax],rbx\n  je initiateEnemyApocalypse\n  \/\/ This will point to our ability manager for SOME enemies when we're responsible for the damage.\n  mov rbx,[rsp+2A]\n  cmp [rax],rbx\n  je initiateEnemyApocalypse  \n  \/\/ This will point to our root structure for a select few enemies when we're responsible for the damage.\n  mov rax,player\n  mov rbx,[rsp+432]\n  cmp [rax],rbx\n  je initiateEnemyApocalypse\n  jmp initiateApocalypseExit  \nverifyPlayerDamaged:\n  \/\/ If our ability manager is the data source, then this set to 0 indicates a vital stat amount is changing\n  \/\/ for Geralt.  \n  mov eax,[rsp+C2]\n  cmp eax,0\n  jne verifyCiriDamaged\n  \/\/ Check if Geralt's stamina is changing.\n  \/\/ This is 0 when stamina is changing.\n  mov eax,[rsp+72]\n  cmp eax,0\n  je initiateApocalypseExit\n  \/\/ If stamina is not changing, check if Geralt's health is changing.\n  \/\/ This is 0 when health is changing.\n  mov rax,[rsp+A2]\n  cmp eax,0\n  jne initiateApocalypseExit  \n  \/\/ This must point to something, it just can't point to a function.\n  mov rbx,[rsp+8A]\n  push rcx\n  lea rcx,[rbx]\n  call checkBadPointer\n  cmp ecx,0\n  pop rcx  \n  jne initiateApocalypseExit  \n  \/\/ If this points to something, it must not be a function. If it is, then the operation is the result\n  \/\/ of a recurring regenerative type function. If it isn't, then this operation is being caused by damage\n  \/\/ from an enemy.\n  mov rax,[rbx]\n  cmp ax,0xFA58\n  jne initiatePlayerApocalypse\n  jmp initiateApocalypseExit  \nverifyCiriDamaged:\n  \/\/ For Ciri, this is not 0 (unlike Geralt) when (assumingly) stamina is changing.\n  \/\/ If it is 0, then Ciri may be losing health.\n  mov eax,[rsp+72]\n  cmp eax,0\n  jne initiateApocalypseExit\n  \/\/ For Ciri, if stamina isn't changing, then this is not 0 when losing health.\n  \/\/ No check for a recurring function is required for Ciri.\n  mov rax,[rsp+A2]\n  cmp eax,0\n  je initiateApocalypseExit  \ninitiatePlayerApocalypse:\n  \/\/ Push the damage amount parameter.\n  movss xmm1,[rsp+62]\n  sub rsp,8\n  movd [rsp],xmm1\n  \/\/ Push the player's current working health value.\n  sub rsp,8\n  movd [rsp],xmm0\n  \/\/ Push the player's maximum health value.\n  mov rax,playerVitals\n  mov rbx,[rax]\n  movss xmm1,[rbx+4]\n  sub rsp,8\n  movd [rsp],xmm1\n  \/\/ Align the player's location struct to the X coordinate and push it.\n  mov rax,playerLocation\n  mov rbx,[rax]\n  lea rax,[rbx+1B8]\n  push rax\n  call executePlayerApocalypse\n  jmp initiateApocalypseUpdateDamage\ninitiateEnemyApocalypse:  \n  \/\/ Push the damage amount parameter.\n  movss xmm1,[rsp+62]\n  sub rsp,8\n  movd [rsp],xmm1\n  \/\/ Push the target's current working health value.\n  sub rsp,8\n  movd [rsp],xmm0\n  call executeEnemyApocalypse\ninitiateApocalypseUpdateDamage:\n  \/\/ Commit updated damage and working health.\n  mov [rsp+62],eax\n  movd xmm0,ebx\ninitiateApocalypseExit:\n  pop rbx\n  pop rax\n  movdqu xmm1,[rsp]\n  add rsp,10\ninitiateApocalypseOriginalCode:\n  popf\n  subss xmm0,[rsp+40]\n  jmp initiateApocalypseReturn\nomnifyApocalypseHook:\n  jmp initiateApocalypse\n  nop \ninitiateApocalypseReturn:\n\ncoordinatesAreDoubles:\n  dd 1\n\nnegativeVerticalDisplacementEnabled:\n  dd 0\n\nyIsVertical:\n  dd 0\n<\/pre>\n\n\n<p>And does it work? Oh you bet it works. And let me say: <em>The Witcher 3<\/em> with the Apocalypse system is <em>freaking fantastic<\/em>. It&#8217;s so fun, and I&#8217;m getting my butt whipped like you wouldn&#8217;t believe.<\/p>\n\n\n\n<p>I can&#8217;t wait to play more of this game with Apocalypse system support, which you can catch live on my <a href=\"https:\/\/twitch.tv\/omni\" target=\"_blank\" rel=\"noreferrer noopener\">stream<\/a>. Please check it out, it&#8217;s going to be an amazing time! And of course, we&#8217;ll be adding more of the Omnified systems to the game as the days progress.<\/p>\n\n\n\n<p>Follow my stream and say hello the next time you see me streaming &#8212; <a href=\"https:\/\/discord.gg\/omni\" target=\"_blank\" rel=\"noreferrer noopener\">join my Discord<\/a> to get real time notifications as to when that happens. Otherwise, check out the <a href=\"https:\/\/badecho.com\/index.php\/tag\/schedule\/\" target=\"_blank\" rel=\"noreferrer noopener\">schedule<\/a>.<\/p>\n\n\n\n<p>For my next article, we&#8217;ll be implementing the Predator system. See you then.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Now that we&#8217;ve had the opportunity to do some basic analysis of the data structures for The Witcher 3, it&#8217;s [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[9,60],"tags":[26,24,22],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v14.9 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\r\n<title>Hacking The Witcher 3 - Part 2 (Apocalypse System) - omni&#039;s hackpad<\/title>\r\n<meta name=\"description\" content=\"Time to overhaul The Witcher 3&#039;s damage system by adding the first of my game-neutral Omnified systems: the Apocalypse system.\" \/>\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\/04\/12\/hacking-witcher-part-2\/\" \/>\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 The Witcher 3 - Part 2 (Apocalypse System) - omni&#039;s hackpad\" \/>\r\n<meta property=\"og:description\" content=\"Time to overhaul The Witcher 3&#039;s damage system by adding the first of my game-neutral Omnified systems: the Apocalypse system.\" \/>\r\n<meta property=\"og:url\" content=\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/\" \/>\r\n<meta property=\"og:site_name\" content=\"omni&#039;s hackpad\" \/>\r\n<meta property=\"article:published_time\" content=\"2021-04-12T13:17:16+00:00\" \/>\r\n<meta property=\"article:modified_time\" content=\"2021-08-25T18:26:34+00:00\" \/>\r\n<meta property=\"og:image\" content=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/WitcherLogo-e1617575127960.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\/04\/12\/hacking-witcher-part-2\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/04\/WitcherLogo-e1617575127960.png\",\"width\":366,\"height\":181},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#webpage\",\"url\":\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/\",\"name\":\"Hacking The Witcher 3 - Part 2 (Apocalypse System) - omni&#039;s hackpad\",\"isPartOf\":{\"@id\":\"https:\/\/badecho.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#primaryimage\"},\"datePublished\":\"2021-04-12T13:17:16+00:00\",\"dateModified\":\"2021-08-25T18:26:34+00:00\",\"description\":\"Time to overhaul The Witcher 3's damage system by adding the first of my game-neutral Omnified systems: the Apocalypse system.\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/\"]}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#webpage\"},\"author\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"headline\":\"Hacking The Witcher 3 &#8211; Part 2 (Apocalypse System)\",\"datePublished\":\"2021-04-12T13:17:16+00:00\",\"dateModified\":\"2021-08-25T18:26:34+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#webpage\"},\"publisher\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"image\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/04\/12\/hacking-witcher-part-2\/#primaryimage\"},\"keywords\":\"Apocalypse,Hacking,Omnifying\",\"articleSection\":\"Games,Witcher 3\",\"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\/1477"}],"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=1477"}],"version-history":[{"count":19,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/1477\/revisions"}],"predecessor-version":[{"id":1947,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/1477\/revisions\/1947"}],"wp:attachment":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/media?parent=1477"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/categories?post=1477"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/tags?post=1477"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}