Here's how they're stored:
Code: Select all
enum ItemEnhancementTypes
{
etNone = 0x0000,
etBinaryEnhancement = 0x0001,
etLoseEnhancement = 0x0002, // Lose enhancements
etStrengthen = 0x0100, // +hp, data1 = %increase (10% increments)
etRegenerate = 0x0200, // data1 = rate
etReflect = 0x0300, // data2 = damage type reflected
etRepairOnHit = 0x0400, // repair damage on hit, data2 = damage type of hit
etResist = 0x0500, // -damage, data1 = %damage adj
etResistEnergy = 0x0600, // -energy damage, data1 = %damage adj (90%, 80%, etc)
etResistMatter = 0x0700, // -matter damage, data1 = %damage adj (90%, 80%, etc)
etResistByLevel = 0x0800, // -damage, data1 = %damage adj, data2 = damage type
etResistByDamage = 0x0900, // -damage, data1 = %damage adj, data2 = damage type
etResistByDamage2 = 0x0a00, // -damage, data1 = %damage adj, data2 = damage type
etSpecialDamage = 0x0b00, // Immunity to damage effects:
// data2 = 0: immune to radiation
// data2 = 1: immune to blinding
// ... see SpecialDamageTypes
etImmunityIonEffects = 0x0c00, // Immunity to ion effects (blinding, EMP, etc.)
// (if disadvantage, interferes with shields)
etPhotoRegenerate = 0x0d00, // regen near sun
etPhotoRecharge = 0x0e00, // refuel near sun
etPowerEfficiency = 0x0f00, // power usage decrease, 01 = 90%/110%, 02 = 80%/120%
etSpeedOld = 0x1000, // decrease cycle time
etTurret = 0x1100, // weapon turret, data1 is angle
etMultiShot = 0x1200, // multiple shots, data2 = count, data1 = %weakening
etSpeed = 0x1300, // decrease cycle time
// A = adj (0-100)
// [if disavantage] adj by 5% starting at 100%.
//
// B = min delay in ticks (do not decrease below this; 0 = no limit)
// C = max delay in ticks (do not increase above this; 0 = no limit)
etConferSpecialDamage = 0x1400, // weapon gains special damage
// A = SpecialDamageTypes
// B = damage level
etHPBonus = 0x1500, // +hp%, like etStrengthen
// X = %increase
etData1Mask = 0x000f, // 4-bits of data (generally for damage adj)
etData2Mask = 0x00f0, // 4-bits of data (generally for damage type)
etTypeMask = 0x7f00, // Type
etDisadvantage = 0x8000, // If set, this is a disadvantage
etDataAMask = 0x000000ff, // 8-bits of data
etDataAMax = 255,
etDataBMask = 0x00ff0000, // 8-bits of data
etDataBMax = 255,
etDataCMask = 0xff000000, // 8-bits of data
etDataCMax = 255,
etDataXMask = 0xffff0000, // 16-bits of data
etDataXMax = 65535,
};
Enhancements are stored as a DWORD, 8 hexadecimal digits (0-9, A-F), like this: 0x00000000. However, often only the last (rightmost) 4 digits will be shown, like this: 0x0000. (In this case the rest are 0.)
The type of the enhancement is stored here: 0x00000000 or 0x0000. If the left one of those two digits is 8 or greater, the enhancement has a negative effect, and you subtract 8 from that digit before figuring out the enhancement type. The enhancement types are listed in the first part of the code above.
The other digits store data about the enhancement. The first four digits are DataX, or DataC followed by Data B (two digits each). The last two digits are DataA or Data2 followed by Data1 (one digit each).
Some enhancement types require searching the code to figure out exactly how they work.
- The ones that use Data1 to store a numerical value tend to go in 10% increments.
- In the case of etSpeedOld, DataA is the adjustment. If it's a positive enhancement, the cycle time is reduced by 10% * DataA. So 0x1002 (applied by weapon enhancement ROM) is 80% cycle time, or 25% faster fire/activation rate. If DataA is not in the range of 0 to 9, it's treated as 9 (10x fire rate). If it's a negative enhancement, it has the reciprocal effect, so 0x9001 would make a device 90% as fast.
Here's the code that determines what happens when you apply an enhancement. It's complicated, but there's some useful information. For instance, an enhancement can be replaced by an enhancement of the same type if the new one is better or affects a different damage type. A positive enhancement can remove a negative enhancement of the same type, or the damaged status. And a regenerating enhancement can remove any negative enhancement.
Code: Select all
EnhanceItemStatus CItemEnhancement::Combine (const CItem &Item, CItemEnhancement Enhancement)
// Combine
//
// Combine the current enhancement with the given one
{
DWORD dwNewMods = Enhancement.m_dwMods;
// If we're losing the enhancement, then clear it
if (dwNewMods == etLoseEnhancement)
{
if (IsEnhancement())
{
*this = CItemEnhancement();
return eisEnhancementRemoved;
}
else
return eisNoEffect;
}
// If the item is not currently enhanced, then we take the new enhancement
else if (m_dwMods == etNone)
{
// For strength/hpBonus, use the following rules:
//
// etStrengthen 0 -> Min(10%, maxHPBonus)
// etStrengthen {level} -> Min( {level} * 10, maxHPBonus )
if (Enhancement.GetType() == etStrengthen
|| Enhancement.GetType() == etHPBonus)
{
int iMaxBonus = Item.GetType()->GetMaxHPBonus();
int iNewBonus = Min((Enhancement.IsStacking() ? 10 : Enhancement.GetHPBonus()), iMaxBonus);
if (iNewBonus > 0)
{
SetModBonus(iNewBonus);
return eisOK;
}
else
return eisNoEffect;
}
// For all others, take the enhancement
else
*this = Enhancement;
return eisOK;
}
// If already enhanced
else if (m_dwMods == dwNewMods)
{
if (IsDisadvantage())
return eisNoEffect;
else
return eisAlreadyEnhanced;
}
// We currently have a disadvantage
else if (IsDisadvantage())
{
// We have a disadvantage and the enhancement is another
// disadvantage.
if (Enhancement.IsDisadvantage())
{
switch (Enhancement.GetType())
{
// If we're making the disadvantage worse, then
// continue; otherwise, no effect.
case etRegenerate:
case etResist:
case etResistEnergy:
case etResistMatter:
case etPowerEfficiency:
{
if (Enhancement.GetType() == GetType()
&& Enhancement.GetLevel() > GetLevel())
{
*this = Enhancement;
return eisWorse;
}
else
return eisNoEffect;
}
case etHPBonus:
case etStrengthen:
{
if ((GetType() == etHPBonus || GetType() == etStrengthen)
&& Enhancement.GetHPBonus() < GetHPBonus())
{
*this = Enhancement;
return eisWorse;
}
else
return eisNoEffect;
}
case etSpeed:
case etSpeedOld:
{
if ((GetType() == etSpeed || GetType() == etSpeedOld)
&& Enhancement.GetActivateRateAdj() > GetActivateRateAdj())
{
*this = Enhancement;
return eisWorse;
}
else
return eisNoEffect;
}
case etResistByLevel:
case etResistByDamage:
case etResistByDamage2:
{
if (Enhancement.GetType() == GetType()
&& Enhancement.GetDamageType() == GetDamageType()
&& Enhancement.GetLevel() > GetLevel())
{
*this = Enhancement;
return eisWorse;
}
else
return eisNoEffect;
}
// Otherwise, a disadvantage does not affect a disadvantage
default:
return eisNoEffect;
}
}
// We have a disadvantage and we use an enhancement.
else
{
switch (Enhancement.GetType())
{
// Regeneration enhancement always repairs a disadvantage
case etRegenerate:
{
*this = CItemEnhancement();
return eisRepaired;
}
// If the enhancement is the opposite of the disadvantage
// then the disadvantage is repaired.
case etResist:
case etResistEnergy:
case etResistMatter:
case etPowerEfficiency:
case etResistByLevel:
case etResistByDamage:
case etResistByDamage2:
case etReflect:
{
if (GetType() == Enhancement.GetType())
{
*this = CItemEnhancement();
return eisRepaired;
}
else
return eisNoEffect;
}
case etHPBonus:
case etStrengthen:
{
if (GetType() == etHPBonus || GetType() == etStrengthen)
{
*this = CItemEnhancement();
return eisRepaired;
}
else
return eisNoEffect;
}
case etSpeed:
case etSpeedOld:
{
if (GetType() == etSpeed || GetType() == etSpeedOld)
{
*this = CItemEnhancement();
return eisRepaired;
}
else
return eisNoEffect;
}
// Otherwise, no effect
default:
return eisNoEffect;
}
}
}
// We currently have an enhancement
else
{
if (!Enhancement.IsDisadvantage())
{
switch (Enhancement.GetType())
{
case etHPBonus:
case etStrengthen:
{
if (GetType() != etHPBonus
&& GetType() != etStrengthen)
return eisNoEffect;
// If improving...
int iOldBonus = GetHPBonus();
int iMaxBonus = Item.GetType()->GetMaxHPBonus();
int iNewBonus = Min((Enhancement.IsStacking() ? iOldBonus + 10 : Enhancement.GetHPBonus()), iMaxBonus);
if (iNewBonus > iOldBonus)
{
SetModBonus(iNewBonus);
return eisBetter;
}
else
return eisNoEffect;
}
// If this is the same type of enhancement and it is better,
// then take it (otherwise, no effect)
case etRegenerate:
case etResist:
case etResistEnergy:
case etResistMatter:
case etPowerEfficiency:
{
if (Enhancement.GetType() == GetType()
&& Enhancement.GetLevel() > GetLevel())
{
*this = Enhancement;
return eisBetter;
}
else
return eisNoEffect;
}
case etSpeed:
case etSpeedOld:
{
if (Enhancement.GetType() == GetType()
&& Enhancement.GetActivateRateAdj() < GetActivateRateAdj())
{
*this = Enhancement;
return eisBetter;
}
else
return eisNoEffect;
}
case etResistByLevel:
case etResistByDamage:
case etResistByDamage2:
{
if (Enhancement.GetType() != GetType())
return eisNoEffect;
else if (Enhancement.GetDamageType() != GetDamageType())
{
*this = Enhancement;
return eisEnhancementReplaced;
}
else if (Enhancement.GetLevel() > GetLevel())
{
*this = Enhancement;
return eisBetter;
}
else
return eisNoEffect;
}
default:
return eisNoEffect;
}
}
else
{
// A disadvantage always destroys any enhancement
*this = CItemEnhancement();
return eisEnhancementRemoved;
}
}
}