johnnylump Posted June 4, 2013 Share Posted June 4, 2013 Confirmed. The reload icon does not appear at all unless the weapon is empty. Link to comment Share on other sites More sharing options...
johnnylump Posted June 4, 2013 Share Posted June 4, 2013 Might be the source of the problem? XComGame >> UITacticalHUD_AbilityContainer >> BuildAbilities () // End:0x264 if(kAbility.GetType() == 45) { kActiveWeapon = kUnit.GetInventory().GetActiveWeapon(); // End:0x24B if((kActiveWeapon != none) && kActiveWeapon.iAmmo <= 0) { m_arrAbilities.InsertItem(0, kAbility); ++ forceAbilitySlot; } // End:0x261 else { m_arrAbilities.AddItem(kAbility); } } I'm pretty sure ability 45 is reload ... but there must be some logic somewhere else that prevents the ability from being added if ammo >= 100. perhaps changing kActiveWeapon.iAmmo <= 0) to <= 200 would do the trick, but not sure. Link to comment Share on other sites More sharing options...
Amineri Posted June 4, 2013 Author Share Posted June 4, 2013 Okay, after some additional thought I have an entirely new approach to deal with the inability-to-fire/cant-reload issue being caused by the native code checks. This new approach would limit firing and suppression properly (might still be some issues with Flush if it's new ammo usage is turned down though) and still allow reloading as usual. It involves a bit more misdirection specifically aimed at fooling the native code... Vanilla weapons all have 4 / 8 shots or 3 / 6 shots for Heavy weapons. In terms of ammo usage that is 25 / 12 or 33 / 16 ammo used per shot. Clearly the native code limits the use of an ability based on remaining ammo (e.g. have iAmmo == 50 cannot suppress with eWP_Heavy weapon). For non-ammo conservation situation, there are the following breaks:iAmmo ==20 : cannot shoot or suppress any weaponiAmmo == 40 : can shoot any weapon but cannot suppress with any weaponiAmmo == 70 : can shoot or suppress with any weapon For ammo conservation situation, there are the following breaks:iAmmo == 10: cannot shoot or suppress any weaponiAmmo == 20: can shoot any weapon but cannot suppress with any weaponiAmmo == 35: can shoot or suppress with any weapon So, my solution is to NOT use the XGWeapon.iAmmo variable any longer to store the remaining ammo. Instead, iAmmo will be set to the specific value above after a shot is taken specifically to cause the native code to allow/suppress abilities correctly (Flush apparently uses a lot of ammo in vanilla, so it may be unavailable when suppression is unavailable -- will need more testing). To hold the actual ammo count I plan to use the XG_Weapon.m_iTurnFired variable, which is currently only used to store a 1 to store whether a weapon overheated, and overheat functionality was disabled and no-one wants it back :) Since the process of setting ammo would be more complicated with this change, requiring both setting the m_iTurnFired variable to record the ammo used and setting the iAmmo variable to make the native code exhibity the correct behavior, I'll have to get rid of the ApplyAmmoCost function, and wrap the ammo-setting functionality into the new ammo-retrieval function XGWeapon.GraduatedOdds. I have one unused parameter left in that function (a class) which I can leave as none or set non-none to flag whether GraduatedOdds should update the ammo or just return the ammo consumed. The only case this flag would be set is in XGAbilityTree.ApplyActionCost. When setting ammo, the GraduatedOdds functions will test the ammo per shot, the real amount of remaining ammo stored in m_TurnFired, whether Ammo Conservation is enabled, and will set the iAmmo value accordingly to generate correct behavior from the native code in terms of ability availability. The GetRemainingAmmo function will be changed to return m_iTurnFired instead of iAmmo. There are a couple of places in the upk code where iAmmo is accessed or set directly -- those will be patched to access m_iTurnFired instead. --------------------------- As for Flush, I'm going to change its default ammo consumption to equal that of Suppression. I have some other thoughts in mind to make flush more viable. In truth I think Flush is actually a quite viable skill already, but is pretty underappreciated due to it being placed opposite to the incredibly useful Rapid Fire. Flush does the following already in vanilla:Grants +30 to aim for the shot (an AMAZING amount) Forces the targetted unit to move at least 7.5 tiles from its current position (480.0 UE units) Shot does 50% of normal damage Consumes additional ammo (not sure how much more -- 2x or 3x?)If necessary the amount the damage is reduce could be modified to maybe 60% or so, but with a +30 aim adding much to damage could quickly become overpowered. Flush nearly negates full cover with its aim bonus, so letting it do any more than 50% damage would be pretty OP. Link to comment Share on other sites More sharing options...
johnnylump Posted June 4, 2013 Share Posted June 4, 2013 I actually think flush is fine, just in a poor place in the vanilla assault perk tree. It's great for finishing off badly wounded aliens. Other than suppression, the other biggie that is OP by the any-action-with-any-ammo feature is Rapid Fire -- my assault rifles have three bursts per magazine, but the trooper was able to use it twice. Link to comment Share on other sites More sharing options...
Yzaxtol Posted June 4, 2013 Share Posted June 4, 2013 Main reason I didn't give Flush to Heavys was that if using Unlimited Ammo it becomes an insanely awesome ability. So I left it with Support, the ability doesn't need to be changed as we've already re-balanced it but it should still cost as much ammo as Suppression and I believe it probably does 2.5 as plenty of times after a flush in vanilla there used to be tiny bit of ammo left but not enough to actually fire the weapon. Link to comment Share on other sites More sharing options...
Amineri Posted June 4, 2013 Author Share Posted June 4, 2013 I actually think flush is fine, just in a poor place in the vanilla assault perk tree. It's great for finishing off badly wounded aliens. Other than suppression, the other biggie that is OP by the any-action-with-any-ammo feature is Rapid Fire -- my assault rifles have three bursts per magazine, but the trooper was able to use it twice. Good call pointing issue with Rapid Fire having the similar issues. I've changed the default ammo usage for flush to require 2 shots just as suppression does. Here's my prototype for setting iAmmo so that the native code does/doesn't restrict abilities appropriately: if(kHumanPlayer != none) // check to see should assign ammo instead of just returning ammo used { m_iTurnFire -= iAdjustment; // remove ammo used if(m_iTurnFired >= (100/iFactor)) // has enough ammo to fire { if(bCantLose) // has Ammo Conservation { iAmmo = 20; // set iAmmo to allow Fire action but not Suppression } else // doesn't have Ammo Conservations { iAmmo = 40; // set iAmmo to allow Fire action but not Suppression } } if(m_iTurnFired >= 2* (100/iFactor)) // has enough ammo to suppress { iAmmo = 90; // set iAmmo to allow any ability to be used, and Reload available } if(m_iTurnFired < (100 / iFactor)) // not enough ammo to do anything { iAmmo = 0; // set iAmmo to empty m_iTurnFired = 0; // set actual ammo to empty } } I think that 20 ammo is sufficient to fire but not suppress with any weapon in vanilla if A.C. is complete. (LMG uses 16 ammo per shot, all else uses 12)Same for 40 ammo if A.C. is not complete (LMG uses 33 ammo per shot, all else uses 25)Setting to 90 ammo should allow reloading after any shot action is taken that uses ammoSetting to 0 should inhibit any firing-type actions under all circumstances. Hopefully this will fix the Suppression and Rapid Fire issues, make it so that abilities can be used appropriately to the actual ammo remaining, and allow for reloading when any ammo is used. Next I have to look into the reload function to see if I can properly set both variable, or come up with some alternative. Link to comment Share on other sites More sharing options...
johnnylump Posted June 4, 2013 Share Posted June 4, 2013 On reloading, it wouldn't be the end of the world if the icon was always there, even if the gun was already fully loaded. Presumably having ammo >= 100 is setting turning off the reload icon. Link to comment Share on other sites More sharing options...
Amineri Posted June 4, 2013 Author Share Posted June 4, 2013 Okay, hopefully third time is the charm! I've reworked the ammo system a bit more. XGWeapon.iAmmo no longer stores the current ammo -- instead it is set in order to produce desired effect in native code (ability availability)XGWeapon.m_iTurnFired now holds current ammo -- default set to 100XGAbility_Targeted.GraduatedOdds (new ammocost function) will set iAmmo and m_iTurnFired if a non-null value is passed in 2nd parametervarious other function changes to support this systemFunctionally it should do the following:Reload ability is available at all times excepting when ammo is fullSuppression / flush should be unavailable when ammo is low (less than 2x single shot left)Flush default ammo usage is double, like SuppressionRegular shots should be available until clip shows empty -- upon reaching ammo < single shot, ammo is set to 0clip-sizes up to 12 should work as before (setting 13 shots will allow 14 due to round-off error)Here is the complete hex code (before/after relative to vanilla): All hex changes for Ammo Cost mod Change to make ApplyAmmoCost into a helper function to reset ammo upon reload original hex:52 B9 00 00 50 55 00 00 00 00 00 00 3C B9 00 00 00 00 00 00 00 00 00 00 3D B9 00 00 00 00 00 00 D9 00 00 00 45 1A 00 00 31 00 00 00 21 00 00 00 A2 01 1E B9 00 00 00 3D B9 00 00 16 07 2E 00 9A 01 1E B9 00 00 26 16 0F 01 1E B9 00 00 25 04 0B 53 new hex: (virtual 0x2D)52 B9 00 00 50 55 00 00 00 00 00 00 3C B9 00 00 00 00 00 00 00 00 00 00 3D B9 00 00 00 00 00 00 D9 00 00 00 45 1A 00 00 2D 00 00 00 21 00 00 00 0F 01 1C B9 00 00 00 3D B9 00 00 0F 01 1E B9 00 00 2C 64 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 04 0B 53 Remove call to ApplyAmmoCost in XGAbilityTree.ApplyActionCost original hex:kAbility.m_kWeapon.ApplyAmmoCost(iCost); (61=0x3D virtual) (41=0x29 file) 20=0x14 delta19 19 00 C4 7E 00 00 09 00 E8 BB 00 00 00 01 E8 BB 00 00 13 00 00 00 00 00 00 1B EF 03 00 00 00 00 00 00 00 C3 7E 00 00 16 new hex:null ops00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B --------------------------------------------- Change XGAbilityTree.ApplyActionCost to call XGAbility_Targeted.GraduatedOdds instead of XGTacticalGameCore.GetAmmoCost original hex for just function: (next 0x1EB)iCost = XComGameReplicationInfo(class'Engine'.static.GetCurrentWorldInfo().GRI).m_kGameCore.GetAmmoCost(kAbility.m_kWeapon.GameplayType(), kAbility.GetType(), kAbility.m_kUnit.GetPlayer().HasFoundryHistory(10), kAbility.m_kUnit.GetCharacter().m_kChar, kAbility.m_bReactionFire); (259 file, 379 virtual bytes -- 120 extra)0F 00 C3 7E 00 00 19 19 2E FE 2C 00 00 19 12 20 4F FE FF FF 0A 00 D8 F9 FF FF 00 1C F6 FB FF FF 16 09 00 98 F9 FF FF 00 01 98 F9 FF FF 09 00 F0 2C 00 00 00 01 F0 2C 00 00 13 01 42 10 00 00 00 1B 16 31 00 00 00 00 00 00 38 3A 19 19 00 C4 7E 00 00 09 00 E8 BB 00 00 00 01 E8 BB 00 00 0A 00 E8 9B 00 00 00 1B 92 30 00 00 00 00 00 00 16 19 00 C4 7E 00 00 0A 00 1C 7C 00 00 00 1B 1E 35 00 00 00 00 00 00 16 19 19 19 00 C4 7E 00 00 09 00 E6 7B 00 00 00 01 E6 7B 00 00 0A 00 EB B2 00 00 00 1B 0A 34 00 00 00 00 00 00 16 0C 00 9E 94 00 00 00 1B 7A 36 00 00 00 00 00 00 24 0A 16 19 19 19 00 C4 7E 00 00 09 00 E6 7B 00 00 00 01 E6 7B 00 00 0A 00 63 B4 00 00 00 1B 7B 31 00 00 00 00 00 00 16 09 00 C3 A2 00 00 00 01 C3 A2 00 00 19 00 C4 7E 00 00 0A 00 D2 7B 00 00 00 2D 01 D2 7B 00 00 16 new function call: (next 0x1EB)iCost = kAbility.GraduatedOdds(0, kAbility, kAbility.m_kUnit.GetPlayer().HasFoundryHistory(10)); (92 file, 128 virtual bytes -- 36 extra)0F 00 C3 7E 00 00 19 00 C4 7E 00 00 61 00 B9 7C 00 00 00 1B E1 35 00 00 00 00 00 00 2C 00 00 C4 7E 00 00 19 19 19 00 C4 7E 00 00 09 00 E6 7B 00 00 00 01 E6 7B 00 00 0A 00 EB B2 00 00 00 1B 0A 34 00 00 00 00 00 00 16 0C 00 9E 94 00 00 00 1B 7A 36 00 00 00 00 00 00 24 0A 16 16 0B 0B 0B 0B 0B 0B 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 00 C3 7E 00 00 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B --------------------------------------------- Alter UITacticalHUD_WeaponPanel.SetWeaponAndAmmo to call XGAbility_Targeted.GraduatedOdds instead of XGTacticalGameCore.GetAmmoCost ****TWO IDENTICAL CALLS**** call 2 hex: (identical to call 1 ) (254 file, 370 virtual bytes -- 116 additional)0F 35 C8 FC FF FF 32 F9 FF FF 00 01 00 72 27 00 00 38 3F 19 19 2E FE 2C 00 00 19 12 20 4F FE FF FF 0A 00 D8 F9 FF FF 00 1C F6 FB FF FF 16 09 00 98 F9 FF FF 00 01 98 F9 FF FF 09 00 F0 2C 00 00 00 01 F0 2C 00 00 F5 00 42 10 00 00 00 1B 16 31 00 00 00 00 00 00 38 3A 19 19 00 70 27 00 00 09 00 E8 BB 00 00 00 01 E8 BB 00 00 0A 00 E8 9B 00 00 00 1B 92 30 00 00 00 00 00 00 16 19 00 70 27 00 00 0A 00 1C 7C 00 00 00 1B 1E 35 00 00 00 00 00 00 16 19 19 19 00 70 27 00 00 09 00 E6 7B 00 00 00 01 E6 7B 00 00 0A 00 EB B2 00 00 00 1B 0A 34 00 00 00 00 00 00 16 0C 00 9E 94 00 00 00 1B 7A 36 00 00 00 00 00 00 24 0A 16 19 19 19 00 70 27 00 00 09 00 E6 7B 00 00 00 01 E6 7B 00 00 0A 00 63 B4 00 00 00 1B 7B 31 00 00 00 00 00 00 16 09 00 C3 A2 00 00 00 01 C3 A2 00 00 4A 16 new function call: myValue.N = float(kTAbility.GraduatedOdds(0, none, kTAbility.m_kUnit.GetPlayer().HasFoundryHistory(10))); (101 file, 141 virtual bytes -- 40 extra)0F 35 C8 FC FF FF 32 F9 FF FF 00 01 00 72 27 00 00 38 3F 19 00 70 27 00 00 59 00 B9 7C 00 00 00 1B E1 35 00 00 00 00 00 00 2C 00 2A 19 19 19 00 70 27 00 00 09 00 E6 7B 00 00 00 01 E6 7B 00 00 0A 00 EB B2 00 00 00 1B 0A 34 00 00 00 00 00 00 16 0C 00 9E 94 00 00 00 1B 7A 36 00 00 00 00 00 00 24 0A 16 16 0B 0B 0B 0B 0B 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 00 70 27 00 00 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B --------------------------------------------- Rewrite XGUnit.ReactionWeaponCheck to call XGAbility_Targeted.GraduatedOdds instead of XGTacticalGameCore.GetAmmoCost original hex:CA B7 00 00 50 55 00 00 00 00 00 00 B3 B7 00 00 00 00 00 00 00 00 00 00 B5 B7 00 00 00 00 00 00 F6 31 00 00 88 45 06 00 5F 01 00 00 07 01 00 00 0F 00 B4 B7 00 00 19 1B CC 32 00 00 00 00 00 00 16 0A 00 2C 0A 00 00 00 1B ED 30 00 00 00 00 00 00 16 07 3B 00 72 00 B4 B7 00 00 2A 16 04 28 07 2E 01 96 19 00 B4 B7 00 00 0A 00 3B B9 00 00 00 1B 6A 34 00 00 00 00 00 00 16 19 19 2E FE 2C 00 00 19 12 20 4F FE FF FF 0A 00 D8 F9 FF FF 00 1C F6 FB FF FF 16 09 00 98 F9 FF FF 00 01 98 F9 FF FF 09 00 F0 2C 00 00 00 01 F0 2C 00 00 6F 00 42 10 00 00 00 1B 16 31 00 00 00 00 00 00 38 3A 19 00 B4 B7 00 00 0A 00 E8 9B 00 00 00 1B 92 30 00 00 00 00 00 00 16 2C 07 19 1B 0A 34 00 00 00 00 00 00 16 0C 00 9E 94 00 00 00 1B 7A 36 00 00 00 00 00 00 24 0A 16 19 1B 7B 31 00 00 00 00 00 00 16 09 00 C3 A2 00 00 00 01 C3 A2 00 00 27 16 16 04 28 07 52 01 19 00 B4 B7 00 00 0A 00 47 B9 00 00 00 1B F8 3D 00 00 00 00 00 00 16 04 28 04 27 04 3A B5 B7 00 00 53 new hex: (virtual 0x15B) header:CA B7 00 00 50 55 00 00 00 00 00 00 B3 B7 00 00 00 00 00 00 00 00 00 00 B5 B7 00 00 00 00 00 00 F6 31 00 00 88 45 06 00 5B 01 00 00 07 01 00 00 0F 00 B4 B7 00 00 19 1B CC 32 00 00 00 00 00 00 16 0A 00 2C 0A 00 00 00 1B ED 30 00 00 00 00 00 00 16 07 3B 00 72 00 B4 B7 00 00 2A 16 04 28 0F 00 54 B7 00 00 9E 35 9C 0D 00 00 AA 0D 00 00 00 00 19 00 B4 B7 00 00 09 00 14 B9 00 00 00 01 14 B9 00 00 94 1A 2C 0C 35 D1 0D 00 00 D5 0D 00 00 00 01 19 01 0A 31 00 00 09 00 C3 A2 00 00 00 01 C3 A2 00 00 2C 10 16 16 07 2D 01 96 19 00 B4 B7 00 00 0A 00 3B B9 00 00 00 1B 6A 34 00 00 00 00 00 00 16 12 20 66 7D 00 00 36 00 BC 7C 00 00 00 1B E1 35 00 00 00 00 00 00 00 54 B7 00 00 2A 19 1B 0A 34 00 00 00 00 00 00 16 0C 00 9E 94 00 00 00 1B 7A 36 00 00 00 00 00 00 24 0A 16 16 16 04 28 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B04 27 04 3A B5 B7 00 00 53 --------------------------------------------- Rewrite XGAbility_Targeted.GraduatedOdds into the new Ammo Costing function -- also can apply ammo used original hex:D4 7C 00 00 50 55 00 00 00 00 00 00 B8 7C 00 00 00 00 00 00 00 00 00 00 BF 7C 00 00 00 00 00 00 73 02 00 00 CF 54 00 00 3D 04 00 00 0D 03 00 00 0F 00 BA 7C 00 00 19 19 00 BE 7C 00 00 0A 00 56 94 00 00 00 1B C5 34 00 00 00 00 00 00 16 0A 00 40 AC 00 00 00 1B 95 33 00 00 00 00 00 00 16 07 F2 01 19 19 19 2E 64 2D 00 00 19 12 20 4F FE FF FF 0A 00 D8 F9 FF FF 00 1C F6 FB FF FF 16 09 00 98 F9 FF FF 00 01 98 F9 FF FF 09 00 71 2D 00 00 00 01 71 2D 00 00 09 00 A3 9C 00 00 00 01 A3 9C 00 00 0A 00 A8 9F 00 00 00 2D 01 A8 9F 00 00 07 F2 01 82 81 19 01 E6 7B 00 00 0A 00 B5 32 00 00 00 1B DB 3D 00 00 00 00 00 00 16 16 18 21 00 19 1B 38 34 00 00 00 00 00 00 16 0A 00 B5 32 00 00 00 1B DB 3D 00 00 00 00 00 00 16 16 07 F2 01 82 82 2D 00 BD 7C 00 00 18 5F 00 77 19 2E 64 2D 00 00 2E FE 2C 00 00 19 12 20 4F FE FF FF 0A 00 D8 F9 FF FF 00 1C F6 FB FF FF 16 09 00 98 F9 FF FF 00 01 98 F9 FF FF 09 00 69 2D 00 00 00 01 69 2D 00 00 2A 16 16 18 74 00 81 19 19 2E 64 2D 00 00 2E FE 2C 00 00 19 12 20 4F FE FF FF 0A 00 D8 F9 FF FF 00 1C F6 FB FF FF 16 09 00 98 F9 FF FF 00 01 98 F9 FF FF 09 00 69 2D 00 00 00 01 69 2D 00 00 0A 00 97 4C 00 00 00 2D 01 97 4C 00 00 16 16 04 25 07 08 02 99 00 BA 7C 00 00 2C 04 16 04 1D FF FF FF FF 0F 00 B9 7C 00 00 93 F9 2C 04 19 19 00 BE 7C 00 00 0A 00 56 94 00 00 00 1B C5 34 00 00 00 00 00 00 16 0A 00 87 AC 00 00 00 1B AD 33 00 00 00 00 00 00 16 16 00 BA 7C 00 00 16 07 39 03 82 82 19 01 E6 7B 00 00 0A 00 B5 32 00 00 00 1B DB 3D 00 00 00 00 00 00 16 18 23 00 81 19 1B 38 34 00 00 00 00 00 00 16 0A 00 B5 32 00 00 00 1B DB 3D 00 00 00 00 00 00 16 16 16 18 0D 00 97 00 BF 7C 00 00 25 16 16 0F 00 BB 7C 00 00 91 00 BF 7C 00 00 2C 05 16 07 1E 03 99 00 BF 7C 00 00 2C 32 16 A1 00 BB 7C 00 00 F9 2C 1E 90 19 19 01 E6 7B 00 00 0A 00 EB B2 00 00 00 1B 0A 34 00 00 00 00 00 00 16 09 00 DB 93 00 00 00 01 DB 93 00 00 2C 0F 16 16 16 A1 00 BB 7C 00 00 90 00 B9 7C 00 00 2C 0F 16 16 06 18 04 07 18 04 82 81 19 01 E6 7B 00 00 0A 00 B5 32 00 00 00 1B DB 3D 00 00 00 00 00 00 16 16 18 21 00 19 1B 38 34 00 00 00 00 00 00 16 0A 00 B5 32 00 00 00 1B DB 3D 00 00 00 00 00 00 16 16 0F 00 BB 7C 00 00 90 8F 19 19 1B 38 34 00 00 00 00 00 00 16 0A 00 EB B2 00 00 00 1B 0A 34 00 00 00 00 00 00 16 09 00 DC 93 00 00 00 01 DC 93 00 00 16 2C 0A 16 07 FD 03 82 9A 00 BA 7C 00 00 26 16 18 0B 00 2D 00 BD 7C 00 00 16 0F 00 BB 7C 00 00 8F 00 BF 7C 00 00 16 06 18 04 A1 00 BB 7C 00 00 90 00 B9 7C 00 00 1D E7 FF FF FF 16 16 04 FB 92 00 BF 7C 00 00 00 BB 7C 00 00 16 25 2C 64 16 04 3A BC 7C 00 00 53 new hex : (virtual 0x435)D4 7C 00 00 50 55 00 00 00 00 00 00 B8 7C 00 00 00 00 00 00 00 00 00 00 BF 7C 00 00 00 00 00 00 73 02 00 00 CF 54 00 00 35 04 00 00 0D 03 00 00 0F 00 BB 7C 00 00 25 07 37 00 9B 00 BF 7C 00 00 25 16 0F 00 BB 7C 00 00 9C 00 BF 7C 00 00 1D FF FF 00 00 16 06 CD 00 07 48 00 72 01 E8 BB 00 00 2A 16 04 25 07 6E 00 19 01 E8 BB 00 00 0C 00 4F B9 00 00 00 1B 9A 36 00 00 00 00 00 00 2C 0A 16 04 25 07 92 00 19 01 E8 BB 00 00 0A 00 4D B9 00 00 00 1B D6 3D 00 00 00 00 00 00 16 04 25 0F 00 BB 7C 00 00 35 9C 0D 00 00 AA 0D 00 00 00 00 19 01 E8 BB 00 00 09 00 14 B9 00 00 00 01 14 B9 00 00 07 F6 00 81 2D 00 BD 7C 00 00 16 0F 00 B9 7C 00 00 FD 00 BB 7C 00 00 2C 64 16 06 0D 01 0F 00 B9 7C 00 00 91 00 BB 7C 00 00 2C 64 16 07 3A 01 9B 00 BF 7C 00 00 25 16 0F 00 BA 7C 00 00 9C 95 00 BF 7C 00 00 2C 10 16 2C FF 16 06 8D 01 0F 00 BA 7C 00 00 1A 2C 0C 35 D1 0D 00 00 D5 0D 00 00 00 01 19 19 01 E6 7B 00 00 09 00 0A 31 00 00 00 01 0A 31 00 00 09 00 C3 A2 00 00 00 01 C3 A2 00 00 07 AC 01 97 9C 00 BA 7C 00 00 26 16 25 16 A1 00 B9 7C 00 00 2C 02 16 07 DA 01 97 9C 00 BA 7C 00 00 2C FE 16 25 16 A1 00 B9 7C 00 00 90 2C 01 95 00 BA 7C 00 00 26 16 16 16 0F 00 B9 7C 00 00 FA 00 B9 7C 00 00 2C 01 16 0F 00 BB 7C 00 00 91 2C 64 00 B9 7C 00 00 16 07 B3 03 9A 00 BF 7C 00 00 25 16 07 3F 02 9A 1B 1E 35 00 00 00 00 00 00 16 2C 11 16 0F 00 BB 7C 00 00 90 2C 02 00 BB 7C 00 00 16 07 67 02 9A 1B 1E 35 00 00 00 00 00 00 16 2C 0C 16 0F 00 BB 7C 00 00 90 2C 01 00 BB 7C 00 00 16 07 B3 03 77 00 BE 7C 00 00 2A 16 0F 00 BA 7C 00 00 A2 19 01 E8 BB 00 00 09 00 1C B9 00 00 00 01 1C B9 00 00 00 BB 7C 00 00 16 07 16 03 99 00 BA 7C 00 00 91 2C 64 00 B9 7C 00 00 16 16 07 F5 02 2D 00 BD 7C 00 00 0F 19 01 E8 BB 00 00 09 00 1E B9 00 00 00 01 1E B9 00 00 2C 14 06 16 03 0F 19 01 E8 BB 00 00 09 00 1E B9 00 00 00 01 1E B9 00 00 2C 28 07 56 03 99 00 BA 7C 00 00 90 2C 02 91 2C 64 00 B9 7C 00 00 16 16 16 0F 19 01 E8 BB 00 00 09 00 1E B9 00 00 00 01 1E B9 00 00 2C 5A 07 B3 03 96 00 BA 7C 00 00 91 2C 64 00 B9 7C 00 00 16 16 0F 19 01 E8 BB 00 00 09 00 1E B9 00 00 00 01 1E B9 00 00 2C 00 0F 19 01 E8 BB 00 00 09 00 1C B9 00 00 00 01 1C B9 00 00 2C 00 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 04 00 BB 7C 00 00 53 ----------------------------------------- Disable call to GraduatedOdds in XGAbility_Targeted.AdjustToHit Change first conditional from:if(kPlayer.m_bCantLose || XComTacticalGRI(class'Engine'.static.GetCurrentWorldInfo().GRI).m_kBattle.m_kDesc.m_iDifficulty == 0)07 C2 02 84 19 00 C1 7C 00 00 0A 00 D9 93 00 00 00 2D 01 D9 93 00 00 18 80 00 9A 19 19 19 2E 64 2D 00 00 19 12 20 4F FE FF FF 0A 00 D8 F9 FF FF 00 1C F6 FB FF FF 16 09 00 98 F9 FF FF 00 01 98 F9 FF FF 09 00 71 2D 00 00 00 01 71 2D 00 00 09 00 A3 9C 00 00 00 01 A3 9C 00 00 09 00 B2 9F 00 00 00 01 B2 9F 00 00 25 16 16 to:if(kPlayer.m_bCantLose && XComTacticalGRI(class'Engine'.static.GetCurrentWorldInfo().GRI).m_kBattle.m_kDesc.m_iDifficulty < 0)07 C2 02 82 19 00 C1 7C 00 00 0A 00 D9 93 00 00 00 2D 01 D9 93 00 00 18 80 00 96 19 19 19 2E 64 2D 00 00 19 12 20 4F FE FF FF 0A 00 D8 F9 FF FF 00 1C F6 FB FF FF 16 09 00 98 F9 FF FF 00 01 98 F9 FF FF 09 00 71 2D 00 00 00 01 71 2D 00 00 09 00 A3 9C 00 00 00 01 A3 9C 00 00 09 00 B2 9F 00 00 00 01 B2 9F 00 00 25 16 16 ----------------------------------------- Change to XGGUnit.Reload to reset both by calling ApplyAmmoCost m_iTurnFired and iAmmo original:header:A7 B6 00 00 50 55 00 00 00 00 00 00 90 B6 00 00 00 00 00 00 00 00 00 00 92 B6 00 00 00 00 00 00 7F 2B 00 00 21 75 05 00 A5 00 00 00 79 00 00 00 body:07 95 00 9A 38 3A 01 C1 FE FF FF 38 3A 24 03 16 0F 19 00 92 B6 00 00 09 00 1E B9 00 00 00 01 1E B9 00 00 2C 64 0F 00 91 B6 00 00 1C 3D FC FF FF 20 8D 87 00 00 01 ED F9 FF FF 4A 4A 4A 4A 4A 4A 16 19 00 91 B6 00 00 0B 00 89 87 00 00 00 1B 44 3A 00 00 00 00 00 00 17 16 1B 92 01 00 00 00 00 00 00 00 91 B6 00 00 4A 16 07 A2 00 1B C6 3C 00 00 00 00 00 00 16 04 0B 53 new: (virtual 0xA1)header:A7 B6 00 00 50 55 00 00 00 00 00 00 90 B6 00 00 00 00 00 00 00 00 00 00 92 B6 00 00 00 00 00 00 7F 2B 00 00 21 75 05 00 A1 00 00 00 79 00 00 00 body:07 95 00 9A 38 3A 01 C1 FE FF FF 38 3A 24 03 16 19 00 92 B6 00 00 0C 00 00 00 00 00 00 1B EF 03 00 00 00 00 00 00 2C 64 16 0F 00 91 B6 00 00 1C 3D FC FF FF 20 8D 87 00 00 01 ED F9 FF FF 4A 4A 4A 4A 4A 4A 16 19 00 91 B6 00 00 0B 00 89 87 00 00 00 1B 44 3A 00 00 00 00 00 00 17 16 1B 92 01 00 00 00 00 00 00 00 91 B6 00 00 4A 16 04 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 53 ----------------------------------------- Need to create default value of m_iTurnFired of 100 Change XGWeapon.default.fFiringRate=1.5 into XGWeapon.default.m_iTurnFired=100 original:02 2D 00 00 00 00 00 00 2A 2E 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 C0 3F new:1E 4C 00 00 00 00 00 00 9D 3B 00 00 00 00 00 00 04 00 00 00 00 00 00 00 64 00 00 00 ----------------------------------------- Change XGUnit.SetAutoFiringRate to not make assignment, so that default m_fAutoFiringRate is used original hex:E7 B1 00 00 50 55 00 00 00 00 00 00 D1 B1 00 00 00 00 00 00 00 00 00 00 D2 B1 00 00 00 00 00 00 F8 0E 00 00 3A DE 01 00 16 00 00 00 0E 00 00 00 0F 01 52 AF 00 00 00 D2 B1 00 00 04 0B 53 00 00 00 02 00 02 00 5E 61 00 00 00 00 00 00 new hex:E7 B1 00 00 50 55 00 00 00 00 00 00 D1 B1 00 00 00 00 00 00 00 00 00 00 D2 B1 00 00 00 00 00 00 F8 0E 00 00 3A DE 01 00 16 00 00 00 0E 00 00 00 0B 01 52 AF 00 00 00 D2 B1 00 00 04 0B 53 00 00 00 02 00 02 00 5E 61 00 00 00 00 00 00 ----------------------------------------- Change GetRemainingAmmo to return m_iTurnFired instead of iAmmo original hex:header:50 B9 00 00 50 55 00 00 00 00 00 00 3A B9 00 00 00 00 00 00 00 00 00 00 3B B9 00 00 00 00 00 00 D5 00 00 00 0A 1A 00 00 15 00 00 00 0D 00 00 00 body:04 01 1E B9 00 00 04 3A 3B B9 00 00 53 new hex: (virtual 0x15)header:50 B9 00 00 50 55 00 00 00 00 00 00 3A B9 00 00 00 00 00 00 00 00 00 00 3B B9 00 00 00 00 00 00 D5 00 00 00 0A 1A 00 00 11 00 00 00 0D 00 00 00 body:04 01 1C B9 00 00 04 3A 3B B9 00 00 53 ----------------------------------------- XGAIBehavior.HasPredeterminedAbility original:m_kUnit.GetInventory().GetPrimaryWeapon().GetRemainingAmmo() == 0 (part of)18 4F 00 9A 19 19 19 01 B8 8A 00 00 0A new:m_kUnit.GetInventory().GetPrimaryWeapon().GetRemainingAmmo() <= 0 (part of)18 4F 00 98 19 19 19 01 B8 8A 00 00 0A ----------------------------------------- XGAIBehavior.GetPredeterminedAbility original:if(m_kUnit.GetInventory().GetPrimaryWeapon().GetRemainingAmmo() == 0) (part of)07 EE 00 9A 19 19 19 01 B8 8A 00 00 0A if(m_kUnit.GetInventory().GetPrimaryWeapon().GetRemainingAmmo() <= 0) (part of)07 EE 00 98 19 19 19 01 B8 8A 00 00 0A ----------------------------------------- XGAIAbilityDM.AI_IntangiblesScore original:kWeapon.GetRemainingAmmo() == 0) (part of)18 23 00 9A 19 00 0A 89 00 00 0A 00 3B B9 new:kWeapon.GetRemainingAmmo() <= 0) (part of)18 23 00 98 19 00 0A 89 00 00 0A 00 3B B9 ----------------------------------------- XGAction_Fire.UpdateAimingView original:m_kWeapon.GetRemainingAmmo() == 0 (part of)18 23 00 9A 19 01 E2 82 00 00 0A 00 3B B9 new:m_kWeapon.GetRemainingAmmo() <= 0 (part of)18 23 00 98 19 01 E2 82 00 00 0A 00 3B B9 ----------------------------------------- XGAction_Fire.InternalCompleteAction original:m_kUnit.UnitSpeak(((iAmmoLeft == 0) ? 8 : 7)); (part of)45 9A 00 31 85 00 00 25 16 02 00 24 08 new:m_kUnit.UnitSpeak(((iAmmoLeft <= 0) ? 8 : 7)); (part of)45 98 00 31 85 00 00 25 16 02 00 24 08 ----------------------------------------- UITacticalHUD_WeaponPanel.SetWeaponAndAmmo original:(kWeapon.GetRemainingAmmo() == 0) && (part of)82 9A 19 00 73 27 00 00 0A 00 3B B9 new:(kWeapon.GetRemainingAmmo() <= 0) && (part of)82 98 19 00 73 27 00 00 0A 00 3B B9 Known issues:Developer Console SetAmmo functions will not work correctly (will fix after testing of current version is 'done')Flush may be unavailable in some situations in which Suppression is available, despite both using the same amount of ammo For those who wish to see it, the new AmmoCost function (GraduatedOdds) should decompiles as (this has comments added): function int GraduatedOdds(int iHitChance, XGPlayer kHumanPlayer, bool bCantLose) { local int iAdjustment, iSoldiers, iFactor; iAdjustment = 0; if(iHitChance != 0) // check for passed ammo/perk info { iAdjustment = iHitChance & 0xFFFF; // use passed ammo info } else { if(m_kWeapon == none) { return 0; } if(m_kWeapon.HasProperty(eWP_UnlimitedAmmo)) ((10)) { return 0; } if(m_kWeapon.IsMelee()) { return 0; } iAdjustment = m_kWeapon.m_kTWeapon.iSuppression; // retrieve weapon ammo info is none was supplied in parameter } if(!bCantLose) // doesn't have bHasAmmoConservation { iFactor = iAdjustment % 100; // get NumShots -- no Ammo Conservation } else // has ammo conservation { iFactor = iAdjustment / 100; // get NumShots -- w/ Ammo Conservation } if(iHitChance != 0) // check for passed ammo/perk info { iSoldiers = (iHitChance >> 16) & 0xFF; //use passed perk info } else iSoldiers = m_kUnit.m_kCharacter.m_kChar.aUpgrades[12]; // store perk 12 (vanilla ButtonUp) for later checks } if ((iSoldiers & 1) > 0) // explicitly test for perk 12 (vanilla ButtonUp) assigned through perk tree { iFactor += 2; // add 2 shots for perk -- can be customized separately from item count } if(iSoldiers & 254) > 0) // explicitly test for perk 12 (vanilla ButtonUp) assigned via items { iFactor += 1*(iSoldiers >> 1); // add shots equal to the number of equipped items } iFactor = Max(iFactor, 1); // prevent divide-by-zero errors iAdjustment = 100 / iFactor; // convert NumShots into Ammo Used -- valid for 12 or fewer shots if(iHitChance == 0) { if (GetType() == eAbility_ShotSuppress) ((17)) { iAdjustment = 2 * iAdjustment; } if (GetType() == eAbility_ShotFlush) ((12)) { iAdjustment = 2 * iAdjustment; } if(kHumanPlayer != none) // check to see should assign ammo instead of just returning ammo used { iSoldiers = (m_kWeapon.m_iTurnFired -= iAdjustment); // remove ammo used, store result in iSoldier if(iSoldiers >= (100/iFactor)) // has enough ammo to fire { if(bCantLose) // has Ammo Conservation { m_kWeapon.iAmmo = 20; // set iAmmo to allow Fire action but not Suppression } else // doesn't have Ammo Conservations { m_kWeapon.iAmmo = 40; // set iAmmo to allow Fire action but not Suppression } } if(iSoldiers >= 2* (100/iFactor)) // has enough ammo to suppress { m_kWeapon.iAmmo = 90; // set iAmmo to allow any ability to be used } if(iSoldiers < (100 / iFactor)) // not enough ammo to do anything { m_kWeapon.iAmmo = 0; // set iAmmo to empty m_kWeapon.m_iTurnFired = 0; // set actual ammo to empty } } } return iAdjustment; } Link to comment Share on other sites More sharing options...
Yzaxtol Posted June 5, 2013 Share Posted June 5, 2013 Tried it twice and it crashes on start-up :S Link to comment Share on other sites More sharing options...
Amineri Posted June 5, 2013 Author Share Posted June 5, 2013 (edited) Tried it twice and it crashes on start-up :S Okay, I did a search-compare directly from the above post to my game and found the source of the problem: The following hex change had the incorrect header virtual size (had 0x11, should have had 0x15) Change GetRemainingAmmo to return m_iTurnFired instead of iAmmo original hex: header: 50 B9 00 00 50 55 00 00 00 00 00 00 3A B9 00 00 00 00 00 00 00 00 00 00 3B B9 00 00 00 00 00 00 D5 00 00 00 0A 1A 00 00 15 00 00 00 0D 00 00 00 body: 04 01 1E B9 00 00 04 3A 3B B9 00 00 53 new hex: (virtual 0x15) header: 50 B9 00 00 50 55 00 00 00 00 00 00 3A B9 00 00 00 00 00 00 00 00 00 00 3B B9 00 00 00 00 00 00 D5 00 00 00 0A 1A 00 00 15 00 00 00 0D 00 00 00 body: 04 01 1C B9 00 00 04 3A 3B B9 00 00 53 All other hex in my game is identical. Sorry about that ... too many changes @_@ Edited June 5, 2013 by Amineri Link to comment Share on other sites More sharing options...
Recommended Posts