Jump to content

R&D Unlocking Hidden/Unused Perks


Amineri

Recommended Posts

Presumably one could edit the savegame file. However, I've never looked into this, and am not even sure where savegame data is stored.

 

Also, following the reasoning below, if yakapo were to install the Long War mod (which grants SquadSight automatically at level 1), then opened up the save game and updated his soldier's abilties, saved the game, then reverted the game back to the previous state, the soldier would be granted Squadsight. This wouldn't -change- the perk; it would simply grant Squadsight in addition to the previous choices.

 

-------------------------------------------------------

 

On a related note, it is definitely possible for a soldier to get more than 7 perks. Of course there are the ones that are labeled as "perks" but aren't one of the set of 28 special class-perks.

 

However, when I loaded a vanilla save-game (in which I had a bunch of Colonels already ranked up) with the Long War mod (which highly alters the perk selection trees), all of my soldiers had the icon requiring them to select perks.

 

I found that any class level in which the new class perk tree had two choices, neither of which the character already had, a new selection was required. This could mean selecting new perks at level 3 and level 7, for example. The game required making the level 3 choice before the level 7 choice. All of the previous perks selected (during the vanilla game playthrough) were still available to be used.

 

In some cases both perk choices were highlighted in the new class perk tree (because they weren't opposing choices before.

 

I think that this means that by dynamically manipulating the perk tree structure it could be possible to make more than 7 choices available.

 

For example, at level 6, when the single perk choice is required, the perk tree could be dynamically rewritten to provide two different choices at the level 2 position. The previous level 2 choice would still be applied, but the player would get 2 new perks at level 6, effectively.

 

This might be a lot more trouble than it is worth, but I thought I'd toss it out there.

Link to comment
Share on other sites

  • Replies 40
  • Created
  • Last Reply

Top Posters In This Topic

Presumably one could edit the savegame file. However, I've never looked into this, and am not even sure where savegame data is stored.

 

Also, following the reasoning below, if yakapo were to install the Long War mod (which grants SquadSight automatically at level 1), then opened up the save game and updated his soldier's abilties, saved the game, then reverted the game back to the previous state, the soldier would be granted Squadsight. This wouldn't -change- the perk; it would simply grant Squadsight in addition to the previous choices.

 

-------------------------------------------------------

 

THANKS!!!!! I will try it the next time I get a change to play. Just to review the steps....

 

1. Install long war mod

2. open most recent save game

3. update soldiers abilities (I presume this happens automatically)

4. Uninstall mod

Link to comment
Share on other sites

My current attempt is to make flashbang grenades use the shredder rocket ability and thus check if animation is given by the object or by the ability that triggers it. Since you're so proeficient cracking code you may want to give a hand at this. I recall seeing somewhere checking if certain ability was used (ability 66 I think it was) then it does 4 damage, so in case it works I'm expecting this to be hard coded in a function (as well as shredder duration and increased damage) so that would limit the shredder rocket ability to only flashbang grenades, but that's ok for me.

 

If you'd allow me yet another petition, I'd like to ask you that if browsing through this functions you find where certain perks are applied I'd appreciate if you'd let me know where you've found them. You know, perk values like headshot extra damage (+2) and extra crit change (+30) are defined in constants, but the game doesn't read them. Surprising, right? :P So that's it, I'm not asking you to search this for me, I'll eventualy do it myself, as I want to make some adjustment (sprinter +2 tiles instead of 3, Close&Personal range 6 or 7 tiles not 1 or 2, tactical sense +3% def up to +15% for 5 enemies, and such) but just take note as I'm sure you already do.

 

A lot of the implementation of abilities is handled in native code, unfortunately.

 

However, Shredder extra damage is applied in XGUnit.OnTakeDamage. It's actually right after the section that applies HEAT ammo bonus damage. It depends on a check on the unit taking the damage, IsShredded() evaluating true. I'd guess that the shredder rocket applies a counter to the targetted unit as a side effect, in addition to the damage dealt (which then counts down by 1 at the end of each turn), but I'm not sure where those are applied.

 

----------------------------------------------------------------------------------

 

On the topic of applying perks. The most relevant portion of GivePerk(##) is : ++ m_kChar.aUpgrades[iPerk]

The other stuff in GivePerk() is handling side effects, such as removing the pistol if Rocketeer is granted, stuff like that.

 

However, for most perks, just the ++m_kChar.aUpgrades[iPerk] code should be sufficient to grant a character that perk. There is no call for RemovePerk(), but it should be possible to use he code --m_kChar.aUpgrades[iPerk] to remove an applied perk.

 

These could be applied as side-effects of equipping/unequipping various items in the Loadout code in order to add/remove the perk. I need to test it out a bit more, but I'm hopeful that this will allow perks to be granted as the result of equipping items. (Finding room for all of the conditionals to apply particular perks based on particular item IDs is another issue, however).

 

There is a member element "iStructureReq" of the TItem structure definition that does not appear to be used. This might be re-purposable to store a Perk ID, which is granted when the item is equipped.

 

Something like:

OnEquip:

if(m_kItem.iStructureReq>0)

{

++m_kChar.aUpgrades[m_kItem.iStructureReq];

}

 

and

OnUnequip:

if(m_kItem.iStructureReq>0)

{

--m_kChar.aUpgrades[m_kItem.iStructureReq];

}

 

Then the iStructureReq fields for items could be filled out any place where the ITEMTREE() is accessible and there are spare bytes to be found (and after BuildItems() is called).

Link to comment
Share on other sites

The function XGFacility_Barracks.DEMOAddNewSoldiers has around 1500 hex bytes, and should be safe to completely re-purpose for assigning perks IDs to items.

 

It takes an integer parameter, so would require 15 bytes to call. Ideally it could be squeezed in XGFacility_Barracks.Enter, so that the first time you enter the barracks all of the perk IDs are assigned to the items.

 

I think this could be done by altering this segment of XGFacility_Barracks.Enter:

if(m_bFirstVisit)
{
FirstTimeHelp();
m_bFirstVisit = false;
}

 

to


if(m_bFirstVisit)
{
DEMOAddNewSoldiers(iView);
}

The function call FirstTimeHelp(); and the assignment m_bFirstVisit = false; can be made inside the DEMOAddNewSoldiers function, along with all of the conditional assignments of perk IDs to items.
It would be ideal to make the Perk ID to item assignments in the DGC.ini, but I don't see any free elements that could be re-used for this. The BalanceItem structure doesn't have any free members :(
Edited by Amineri
Link to comment
Share on other sites

If it turns out to work as intended it'd be great to tie certain abilities to specific objects, I see this solves your suppression issue with shivs, also applyable to grenade launcher/bombardier, etc. Imo it will be useful even for abilities that require a number of charges too, because some of them are displayed regardless the player has no initial charges for it, like ghost ability (although this one is a peculiar one 'cause it's an armor ability).

 

In the ini weapons have this "iReactionAngle" value that sets the cone angle in which the weapon can be used, I set them all to 360 to avoid "I see them but cannot shot them" scenarios, if that value were set by script (hardcoded) that value could be left available to set bonus perk.

 

I understand that inside the cannibalized function there's space enough to perform some checks, so perk assignment is'nt automatic, right? If so this seems to me a perfect solution as well for implementing different ammo types, since they could be given a bonus perk (ie, holo-targetting, or heat ammo) and then in that function it could be checked that the main weapon is able to carry that ammo, and otherwise not applying the perk

 

ps: sry I read it wrong, ok I see what you mean, first running that fuction once to build the perk-item mapping and just adding or removing perks when items are un/equipped... well, if a function could be implemented to do the work and thus include some extra check I'd love it, otherwise it still seems pretty good to me

Link to comment
Share on other sites

This would partially solve the issue with applying Suppression to SHIVs. I'm still pretty sure that the native BuildAbilities() call that rebuilds which abilities are currently available (for example, suppressing various abilities after Run and Gun is activated) is looking at the FoundryTech array and giving any SHIV Suppression based on whether the FTech has been researched.

 

So, I think I'd also have to find a way to suppress sending the info over to the tactical game -- that the FTech Suppression has been completed. It's hard to predict what will happen, though. The native code could have hard checks that SHIVs can only get Suppressions if the FTech is finished, and the regular perk only applies the ability to XCOM soldiers.

 

It's like how the conditionals for Bullet Storm went overboard. You have to be a heavy class, using a Heavy weapon, AND have the perk Bullet Storm. (and, of course, the current action has to be Fire_Standard)

 

I'll likely try and do a simple test first -- something like granting Flush if a medikit is equipped -- just to see if the concept works.

Link to comment
Share on other sites

It's a pity that's a black box... is there no way we can see the code for this BuildAbilities func? So far I've tested giving soldiers the smoke grenade perk, which works uncapped, fire rocket and shredder rockt abilities seem to be subject to having a rocket launcher equipped, not to class, and battlescanner works ok (I give them 2 charges for each item of type 99, newly added for building, and it seems by default soldiers already have a battlescanner item in some hidden slot). Maybe this could be a way to bypass some hardcoded check, equipping hidden items in hidden slots, just to pass the check.
Link to comment
Share on other sites

I've been working a little bit on trying to get the bombard ability to work. (It is perk 0x52 = 82)

 

For testing purposes I gave it as the level 1 ability to Support (replacing Smoke Grenade). The perk showed up properly in the info box during tactical missions, but had no effect. I dug into the code a little, and discovered that XGUnit.HasBombardAbility is hard-coded to return true for only the aliens :Cyberdisc, Heavy Floater, Muton Elite, and Sectopod.

 

The relevant function is:

 

 

iType = GetCharacter().m_kChar.iType;
if(iType == 10 || (iType == 11) || (iType == 8) || (iType == 16))
{
return true;
}
return false;
}
I rewrote it so that it includes a check to see if the HasUpgrade(82) check is made as well. My hex code decompiles as:
switch (m_kCharacter.m_kChar.iType)
{
case 8:
case 10:
case 11:
case 16:
return true
default:
break
}
if(m_kCharacter.HasUpgrade(82))
{
return true;
}
return false;
However, it is causing the game to crash when the function is executed.
Here is the hex substitution:

header:
F8 B5 00 00 50 55 00 00 00 00 00 00 E1 B5 00 00 00 00 00 00 00 00 00 00 E3 B5 00 00 00 00 00 00 BE 25 00 00 A0 BF 04 00 91 00 00 00 69 00 00 00
body: (original 105 file, 0x91 virtual bytes)
0F 00 E2 B5 00 00 35 D3 0D 00 00 D5 0D 00 00 00 00 19 1B 7B 31 00 00 00 00 00 00 16 09 00 C3 A2 00 00 00 01 C3 A2 00 00 07 84 00 84 84 84 9A 00 E2 B5 00 00 2C 0A 16 18 0E 00 9A 00 E2 B5 00 00 2C 0B 16 16 18 0E 00 9A 00 E2 B5 00 00 2C 08 16 16 18 0E 00 9A 00 E2 B5 00 00 2C 10 16 16 04 27 04 28 04 3A E3 B5 00 00 53
new:
header:
F8 B5 00 00 50 55 00 00 00 00 00 00 E1 B5 00 00 00 00 00 00 00 00 00 00 E3 B5 00 00 00 00 00 00 BE 25 00 00 A0 BF 04 00 85 00 00 00 69 00 00 00
consolidated:
So, our switch/case would look like: (105 file, 0x85 virtual bytes)
05 D3 0D 00 00 00 35 D3 0D 00 00 D5 0D 00 00 00 00 19 01 0A 31 00 00 09 00 C3 A2 00 00 00 01 C3 A2 00 00 0A 40 00 24 08 0A 45 00 24 0A 0A 4A 00 24 0B 0A 41 00 24 10 04 27 0A FF FF 06 57 00 07 7E 00 19 1B 7B 31 00 00 00 00 00 00 16 0C 00 EA A2 00 00 00 1B B8 36 00 00 00 00 00 00 2C 52 16 04 27 04 28 0B 0B 04 0B 53

both the header and the body have to be swapped. I just keep them separate until I'm all done so it's easier to change the virtual size.

 

I know a few people have worked more with case statements than I have, so maybe someone will see what this is doing wrong.

 

--------------------------------------

 

On a side note - the Bombard ability increases grenade range to = sight range. It might be a little overpowered for a soldier ability...

 

Also, I noticed that frag grenades have slightly less range than alien grenades. Funny the stuff a person misses.

Link to comment
Share on other sites

I haven't tried to write empty cases myself, but that seems to be ok. My guess it's the jump inside the default case, it is unnecessary since it's jumping to the next adjacent position (07 jumpIfNot token), or at least it should point there, so I guess it's ok to remove the jump and leave the default case empty as well. Not sure if it's mandatory to include a default case at all, probably it is.

Link to comment
Share on other sites

Found the issue with the switch case statement. I had an incorrect jump offset (0x41 instead of 0x51). That will do it every time.

 

I have been able to get the Bombadier Perk working, applied via the Perk Tree in Barracks/Abilities.

 

The ability is Bombadier : 82 = 0x52

 

Perk can be swapped in for any other perk as usual.

 

The following hex change is required in XGUnit.HasBombardAbility to make the Perk work, however:

 

 

 

header:
F8 B5 00 00 50 55 00 00 00 00 00 00 E1 B5 00 00 00 00 00 00 00 00 00 00 E3 B5 00 00 00 00 00 00 BE 25 00 00 A0 BF 04 00 91 00 00 00 69 00 00 00 0F 00 E2 B5 00 00 35 D3 0D 00 00 D5 0D 00 00 00 00 19 1B 7B 31 00 00 00 00 00 00 16 09 00 C3 A2 00 00 00 01 C3 A2 00 00 07 84 00 84 84 84 9A 00 E2 B5 00 00 2C 0A 16 18 0E 00 9A 00 E2 B5 00 00 2C 0B 16 16 18 0E 00 9A 00 E2 B5 00 00 2C 08 16 16 18 0E 00 9A 00 E2 B5 00 00 2C 10 16 16 04 27 04 28 04 3A E3 B5 00 00 53
new:
F8 B5 00 00 50 55 00 00 00 00 00 00 E1 B5 00 00 00 00 00 00 00 00 00 00 E3 B5 00 00 00 00 00 00 BE 25 00 00 A0 BF 04 00 85 00 00 00 69 00 00 00 05 D3 0D 00 00 00 35 D3 0D 00 00 D5 0D 00 00 00 00 19 01 0A 31 00 00 09 00 C3 A2 00 00 00 01 C3 A2 00 00 0A 40 00 24 08 0A 45 00 24 0A 0A 4A 00 24 0B 0A 51 00 24 10 04 27 0A FF FF 07 7B 00 19 1B 7B 31 00 00 00 00 00 00 16 0C 00 EA A2 00 00 00 1B B8 36 00 00 00 00 00 00 2C 52 16 04 27 04 28 0B 0B 0B 0B 0B 04 0B 53

Decompiled code should read as:

simulated function bool HasBombardAbility()
{
local int iType;

switch(m_kCharacter.m_kChar.iType)
{
// End:0x40
case 8:
// End:0x45
case 10:
// End:0x4A
case 11:
// End:0x51
case 16:
return true;
// End:0xFFFF
default:
// End:0x7B
if(GetCharacter().HasUpgrade(82))
{
return true;
}
return false;
}
//return;
}

This gives the unit the same ability to throw grenades all the way out to sight distance, the same as the four alien units that have the ability.
My hope is to give it as a perk to SHIVs if they equip a grenade launcher.
I tested this by substituting out the first Support perk choice
2C {Smoke Grenade}
06 4A 01 07 4F 00 9A 00 3B 66 00 00 2C 02 16 07 3A 00 9A 00 3A 66 00 00 25 16 04 2C
to the 0x52 (Bombadier) perk.
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...