Jump to content

Adding new DGC.ini entries


Amineri

Recommended Posts

I already know that it is possible to add new entries to the DGC.ini (embedded in XcomGame.exe). I do this by using ResourceHacker. So far I've been able to add new lines such as adding the SHIV sentry gun and Smoke Grenades to the BuildItems= section.

 

However, looking at how the variables are read and configured, I believe it should be possible to build even more.

 

For example, I've been using the BalanceMods_Easy, and _Normal to alter the alien stats based on number of days elapsed.

 

However, I noticed that the definition of these variables is:

var config array<config TCharacterBalance> BalanceMods_Classic;

 

This means that the array is a dynamic array. Each entry can only contain the values specified in the TCharacterBalance structure (namely Aim, CritHit, etc), but the NUMBER of entries in the BalanceMods_Classic array need not be limited by the number of aliens.

 

A typical entry reads like:

 

BalanceMods_Classic=(eType=eChar_Sectoid, iDamage=0,iCritHit=10,iAim=10,iDefense=0,iHP=1, iMobility=0,iWill=0)
Note that the eType is NOT the array position, but is simply one value of the structure at that point. This is why the various dynamic array can be built "out of order" compared to the arrays in the game (for example, the 'Weapons=' array order does not correspond to the EItem enumerated type order).
Even though the ECharacter enumerated type only goes up to 21 ( 21 = eChar_Max, and 20 = eChar_BattleScanner), it might be possible to create a BalanceMods_Classic entry such as:
BalanceMods_Classic=(eType=30, iDamage=0,iCritHit=10,iAim=10,iDefense=0,iHP=1, iMobility=0,iWill=0)
This should create a valid entry into the dynamic BalanceMods_Classic array, which would be accessed in-game via BalanceMods_Classic[30].
Under existing circumstances this value would never be read, as the existing ModifyStatsByDifficulty function uses only values : BalanceMods_Classic[kCharacter.iType], which limits the reading of the array to the limits of the ECharacter enumerated value type.
---------------------------
So how could this be useful? Well, it's another way to squeeze extra configuration value into the game, which is always handy.
In this particular case, I'm thinking about the possibility of create "hero" aliens. Basically, each alien has some chance to be an upgraded "hero" (say each pod's leader has a 5% chance, just for the sake of something concrete).
Suppose a sectoid "hero" is being made. Instead of applying the regular BalanceMods, we give that alien the stats in : BalanceMods_Classic[eChar_Sectoid + eChar_MAX]
In this case it would be 4 + 21 = 25.
To define the 'hero' sectoid stats (relative to regular sectoid stats) would be configurable via the DGC.ini (new) line:
BalanceMods_Classic=(eType=25, iDamage=3,iCritHit=10,iAim=10,iDefense=0,iHP=4, iMobility=1,iWill=30)
It would even be possible to define multiple tiers of "heroes", using further offsets.
Like ...
4 + 0 = regular sectoid
4 + 21 = level 1 hero sectoid
4 + 21*2 = level 2 hero sectoid
4 + 21*3 = level 3 hero sectoid
etc
--------------------------------------------------
I found this accidentally while poking around the config variables looking for psionic rank names to display in the perk tree, so I'm not actively working on this, but thought I would toss it out there in case other people have ideas for how to use-and-abuse "extra" entries in these dynamic config arrays.

 

Link to comment
Share on other sites

that's really interesting. Using this approach the dynamic stats mod could be tweaked to use several layers of quality for each alien and time progression could just make it so it pushes random choices to higher levels, a la: stats layer = Alien ID + 21 * ( Rand(3) + int(DaysPassed / AlienUpdateTime) ), so there's still randomness and enemy progression.

 

Taking it further, this trick could also be used to give each alien a pool of (up to) 7 perks to choose from, and again, with several layers per alien ...

 

I'm pretty busy as well coding other stuff, I haven't yet implemented DR or regeneration effects (I wanted to code it myself once I finished spendable items ... sooon, very soon :S), but definitively if no one else takes the initiative to mod this out it'll be good to remember this thread :)

Link to comment
Share on other sites

I really like this idea of extending the configuration information :smile:

I haven't looked into it at all and I'm REALLY rusty at modding XCOM now, so ignore me if this is obvious or just wrong. Although the array is dynamic and can potentially be resized, it would likely only be initially sized to contain the number of entries defined in DGC.ini. You'd probably have to pad the intermediate values up to your intended addition.

For example, if you add 1 new entry (eType=25), the array size will increase by only one. Attempting to access the value with BalanceMods_Classic[25] would probably cause an "index out of range" error, as there would only be 22 elements in the array. I'd expect creating dummy entries in between would avoid this, or creating a hero stats for each unit up to your chosen one :smile:

Couldn't you just call it:
BalanceMods_Classic=(eType=HeroSectoid01, iDamage=0,iCritHit=10,iAim=10,iDefense=0,iHP=1, iMobility=0,iWill=0)
and access it by BalanceMods_Classic[22]?

I don't have a good enough understanding of how this works exactly, but it's what I would expect with my limited knowledge :smile:

Link to comment
Share on other sites

I'm not 100% sure on a lot of this either.

 

I have a feeling that the eType=HeroSectoid01 line wouldn't parse correctly. Every time I've seen an enumerated value used, there has been a valid enumerated type in the current code. For character types this is defined in XGGameData:

Quote

 

enum ECharacter

{

 

eChar_None,

eChar_Civilian,

eChar_Soldier,

eChar_Tank,

eChar_Sectoid,

eChar_Floater,

eChar_Thinman,

eChar_Muton,

eChar_Cyberdisc,

eChar_SectoidCommander,

eChar_FloaterHeavy,

eChar_MutonElite,

eChar_Ethereal,

eChar_Chryssalid,

eChar_Zombie,

eChar_MutonBerserker,

eChar_Sectopod,

eChar_Drone,

eChar_Outsider,

eChar_EtherealUber,

eChar_BattleScanner,

eChar_MAX

};

I have a feeling that trying to reference an enumerated value not defined would cause unfortunate side effects.

 

I think you are correct that the dynamic arrays are not built based upon the first key, just in the order that they are declared in the DGC.ini file.

 

An example of this can be seen in the BalanceItems function, which looks like:

Quote

 

if(iBalanceItem < class'XGTacticalGameCore'.default.ItemBalance.Length)

{

 

kBalance = class'XGTacticalGameCore'.default.ItemBalance[iBalanceItem];

m_arrItems[kBalance.eItem].iCash = GetItemCreditCost(kBalance.iCash);

m_arrItems[kBalance.eItem].iElerium = GetItemEleriumCost(kBalance.iElerium);

m_arrItems[kBalance.eItem].iAlloy = GetItemAlloyCost(kBalance.iAlloys);

m_arrItems[kBalance.eItem].iMaxEngineers = kBalance.iEng;

m_arrItems[kBalance.eItem].iHours = GetItemBuildTime(kBalance.eItem, byte(m_arrItems[kBalance.eItem].iCategory), int(float(kBalance.iTime) * Abs(float(m_arrItems[kBalance.eItem].iMaxEngineers))));

// End:0x397 Loop:False

if(IsOptionEnabled(7))

{

// End:0x397 Loop:False

if(m_arrItems[kBalance.eItem].iHours == -1)

{

m_arrItems[kBalance.eItem].iCash /= class'XGTacticalGameCore'.default.SW_MARATHON;

}

}

++ iBalanceItem;

// This is an implied JumpToken; Continue!

goto J0x0b;

}

Note that it pulls the kBalance.eItem field of the ItemBalance[iBalance] entry and uses that as the index for m_arrItems, and not the iBalance counter (which represents the position of the current entry in the ItemBalance array).

 

However, that would mean that the construction that uses the BalanceMods_Easy, etc IS dependent upon the ordering in the DGC.ini.

 

The ModifyStatsByDifficulty function draws directly from the BalanceMods_Easy dynamic array rather than referencing the eType field.

Quote

 

kCharacter.aStats[1] += BalanceMods_Easy[kCharacter.iType].iAim;

kCharacter.aStats[2] += BalanceMods_Easy[kCharacter.iType].iDefense;

kCharacter.aStats[3] += BalanceMods_Easy[kCharacter.iType].iMobility;

kCharacter.aStats[7] += BalanceMods_Easy[kCharacter.iType].iWill;

kCharacter.aStats[13] += BalanceMods_Easy[kCharacter.iType].iCritHit;

kCharacter.aStats[0] += BalanceMods_Easy[kCharacter.iType].iHP;

kCharacter.aStats[12] += BalanceMods_Easy[kCharacter.iType].iDamage;

Presumably this means that changing the order of the BalanceMods entries in the DGC.ini would apply the stat differences to different units ... the eType line appears to be currently ignored.

 

'm guessing that BalanceMods was one of the earlier defined config values. It would have been much more robust to have a single BalanceMods= variable with the eType and eDifficult fields. This would have allowed easier creation of more than four difficulties. Alas, it is not to be.

 

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

 

 

In order to reference the BalanceMods "properly", you'd need to loop through the BalanceMods dynamic array, checking to see if the current character type (or the increased one if you were looking for a "hero" type) matches the field in the BalanceMods_<diff>.eType

 

Something like:

 

eTypeLookingFor = foo; // 4 for sectoid, 25 for level1 hero sectoid, 46 for level2 hero sectoid, etc

iCharType = 0;

if(iCharType < BalanceMods_Classic.Length)

{

if(BalanceMods_Classic[iCharType].eType == iTypeLookingFor)

{

<do stuff>

}

}

 

This would prevent from having to fill out all possibly entries in the BalanceMod area. If a modder only wants certain alien types to have heros, then only those DGC.ini entries need to be created. It's also a lot more robust in general -- having stuff be implicitly defined by order in the DGC.ini is just asking for hard-to-trace bugs.

Edited by Amineri
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...