PRC8/nwn/nwnprc/trunk/include/prc_shifter_info.nss
Jaysyn904 2a7cb1002e Fixed all content filenames over 16 characters
Fixed all content filenames over 16 characters
2024-08-30 19:49:40 -04:00

1437 lines
70 KiB
Plaintext

//:: Updated for .35 by Jaysyn 2023/03/10
#include "prc_inc_function"
#include "inc_nwnx_funcs"
//:: Test Void
//void main (){}
const int DEBUG_NATURAL_AC_CALCULATION = FALSE;
int MAX_BONUS = GetPRCSwitch(PRC_PNP_SHIFTER_BONUS);
const int MAX_PENALTY = 10;
int NWNX_STR_LIMIT = 100 - MAX_BONUS;
struct _prc_inc_ability_info_struct{
int nTemplateSTR;
int nTemplateDEX;
int nTemplateCON;
int nShifterSTR;
int nShifterDEX;
int nShifterCON;
int nDeltaSTR;
int nDeltaDEX;
int nDeltaCON;
int nItemSTR;
int nItemDEX;
int nItemCON;
int nExtraSTR;
int nExtraDEX;
int nExtraCON;
int nItemDeltaSTR;
int nItemDeltaDEX;
int nItemDeltaCON;
};
//TODO: also count item penalties?
struct _prc_inc_ability_info_struct _prc_inc_CountItemAbilities(object oCreature)
{
struct _prc_inc_ability_info_struct rInfoStruct;
rInfoStruct.nItemSTR = 0;
rInfoStruct.nItemDEX = 0;
rInfoStruct.nItemCON = 0;
object oItem;
itemproperty iProperty;
int nSlot;
for(nSlot = 0; nSlot < NUM_INVENTORY_SLOTS; nSlot++)
{
switch (nSlot)
{
case INVENTORY_SLOT_CARMOUR:
case INVENTORY_SLOT_CWEAPON_R:
case INVENTORY_SLOT_CWEAPON_L:
case INVENTORY_SLOT_CWEAPON_B:
break;
default:
{
oItem = GetItemInSlot(nSlot, oCreature);
if (GetIsObjectValid(oItem))
{
iProperty = GetFirstItemProperty(oItem);
while (GetIsItemPropertyValid(iProperty))
{
if (GetItemPropertyType(iProperty) == ITEM_PROPERTY_ABILITY_BONUS &&
GetItemPropertyDurationType(iProperty) == DURATION_TYPE_PERMANENT
)
{
int nSubType = GetItemPropertySubType(iProperty);
int nCostTableValue = GetItemPropertyCostTableValue(iProperty);
if (nSubType == IP_CONST_ABILITY_STR)
rInfoStruct.nItemSTR += nCostTableValue;
else if (nSubType == IP_CONST_ABILITY_DEX)
rInfoStruct.nItemDEX += nCostTableValue;
else if (nSubType == IP_CONST_ABILITY_CON)
rInfoStruct.nItemCON += nCostTableValue;
}
// Next item property.
iProperty = GetNextItemProperty(oItem);
}
}
}
}
}
return rInfoStruct;
}
struct _prc_inc_ability_info_struct _prc_inc_shifter_GetAbilityInfo(object oTemplate, object oShifter)
{
int bFuncs = GetPRCSwitch(PRC_NWNX_FUNCS);
//Initialize with item ability bonuses
struct _prc_inc_ability_info_struct rInfoStruct = _prc_inc_CountItemAbilities(oShifter);
//Get template creature abilities
rInfoStruct.nTemplateSTR = GetAbilityScore(oTemplate, ABILITY_STRENGTH, TRUE);
rInfoStruct.nTemplateDEX = GetAbilityScore(oTemplate, ABILITY_DEXTERITY, TRUE);
rInfoStruct.nTemplateCON = GetAbilityScore(oTemplate, ABILITY_CONSTITUTION, TRUE);
//TODO: merge in "Ability Bonus: Strength" from item property from template hide here (not too important, as not many templates use this)
//TODO: merge in "Ability Bonus: Dexterity" from item property from template hide here (not too important, as not many templates use this)
//TODO: merge in "Ability Bonus: Constitution" from item property from template hide here (not too important, as not many templates use this)
//Calculate how they compare to the shifter's abilities
rInfoStruct.nShifterSTR = GetAbilityScore(oShifter, ABILITY_STRENGTH, TRUE);
rInfoStruct.nShifterDEX = GetAbilityScore(oShifter, ABILITY_DEXTERITY, TRUE);
rInfoStruct.nShifterCON = GetAbilityScore(oShifter, ABILITY_CONSTITUTION, TRUE);
rInfoStruct.nDeltaSTR = rInfoStruct.nTemplateSTR - rInfoStruct.nShifterSTR;
rInfoStruct.nDeltaDEX = rInfoStruct.nTemplateDEX - rInfoStruct.nShifterDEX;
rInfoStruct.nDeltaCON = rInfoStruct.nTemplateCON - rInfoStruct.nShifterCON;
//Handle stat boosting items
if (rInfoStruct.nItemSTR > MAX_BONUS)
rInfoStruct.nItemSTR = MAX_BONUS;
else if (rInfoStruct.nItemSTR < -MAX_PENALTY)
rInfoStruct.nItemSTR = -MAX_PENALTY;
if (rInfoStruct.nItemDEX > MAX_BONUS)
rInfoStruct.nItemDEX = MAX_BONUS;
else if (rInfoStruct.nItemDEX < -MAX_PENALTY)
rInfoStruct.nItemDEX = -MAX_PENALTY;
if (rInfoStruct.nItemCON > MAX_BONUS)
rInfoStruct.nItemCON = MAX_BONUS;
else if (rInfoStruct.nItemCON < -MAX_PENALTY)
rInfoStruct.nItemCON = -MAX_PENALTY;
//Handle changes that exceed bonus or penalty caps
rInfoStruct.nItemDeltaSTR = rInfoStruct.nDeltaSTR + rInfoStruct.nItemSTR;
if (bFuncs)
{
//NWNX boosts aren't capped, so we don't need to handle caps, generally speaking.
rInfoStruct.nExtraSTR = 0;
//However, due to a Bioware issue, if STR, including bonuses, goes greater than 100,
//the amount of weight the PC can carry drops to 0. So, cap STR to make sure this doesn't happen.
if (rInfoStruct.nTemplateSTR > NWNX_STR_LIMIT)
{
rInfoStruct.nExtraSTR = rInfoStruct.nTemplateSTR - NWNX_STR_LIMIT;
rInfoStruct.nTemplateSTR = NWNX_STR_LIMIT;
rInfoStruct.nDeltaSTR = rInfoStruct.nTemplateSTR - rInfoStruct.nShifterSTR;
}
}
else if (rInfoStruct.nItemDeltaSTR > MAX_BONUS)
rInfoStruct.nExtraSTR = rInfoStruct.nItemDeltaSTR - MAX_BONUS;
else if(rInfoStruct.nItemDeltaSTR < -MAX_PENALTY)
rInfoStruct.nExtraSTR = rInfoStruct.nItemDeltaSTR + MAX_PENALTY;
rInfoStruct.nItemDeltaDEX = rInfoStruct.nDeltaDEX + rInfoStruct.nItemDEX;
if (bFuncs)
rInfoStruct.nExtraDEX = 0; //NWNX boosts aren't capped, so we don't need to handle caps
else if (rInfoStruct.nItemDeltaDEX > MAX_BONUS)
rInfoStruct.nExtraDEX = rInfoStruct.nItemDeltaDEX - MAX_BONUS;
else if(rInfoStruct.nItemDeltaDEX < -MAX_PENALTY)
rInfoStruct.nExtraDEX = rInfoStruct.nItemDeltaDEX + MAX_PENALTY;
rInfoStruct.nItemDeltaCON = rInfoStruct.nDeltaCON + rInfoStruct.nItemCON;
if (bFuncs)
rInfoStruct.nExtraCON = 0; //NWNX boosts aren't capped, so we don't need to handle caps
else if (rInfoStruct.nItemDeltaCON > MAX_BONUS)
rInfoStruct.nExtraCON = rInfoStruct.nItemDeltaCON - MAX_BONUS;
else if(rInfoStruct.nItemDeltaCON < -MAX_PENALTY)
rInfoStruct.nExtraCON = rInfoStruct.nItemDeltaCON + MAX_PENALTY;
return rInfoStruct;
}
int _prc_inc_GetItemACBonus(object oItem)
{
int nArmorBonus = 0;
itemproperty iProp = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(iProp))
{
if(GetItemPropertyType(iProp) == ITEM_PROPERTY_AC_BONUS && GetItemPropertyDurationType(iProp) == DURATION_TYPE_PERMANENT)
nArmorBonus = max(nArmorBonus, GetItemPropertyCostTableValue(iProp)); //TODO: pick the biggest? the first? stack them?
iProp = GetNextItemProperty(oItem);
}
return nArmorBonus;
}
int _prc_inc_GetArmorMaxDEXBonus(object oArmor, int nMaxDexACBonus = 100)
{
if (GetIsObjectValid(oArmor))
{
int nArmorAC = GetItemACValue(oArmor) - _prc_inc_GetItemACBonus(oArmor); //Exclude magical AC bonus to figure out armor type
switch(nArmorAC)
{
//TODO: CAN THESE BE LOOKED UP IN A 2DA OR SOMEWHERE?
case 8: case 7: case 6:
nMaxDexACBonus = 1; break;
case 5:
nMaxDexACBonus = 2; break;
case 4: case 3:
nMaxDexACBonus = 4; break;
case 2:
nMaxDexACBonus = 6; break;
case 1:
nMaxDexACBonus = 8; break;
}
}
return nMaxDexACBonus;
}
struct _prc_inc_ac_info_struct{
int nArmorBase;
int nArmorBonus;
int nShieldBase;
int nShieldBonus;
int nDodgeBonus;
int nNaturalBonus;
int nDeflectionBonus;
int nDEXBonus;
};
struct _prc_inc_ac_info_struct _prc_inc_ACInfo(object oTemplate)
{
struct _prc_inc_ac_info_struct ac_info;
object oArmorItem = GetItemInSlot(INVENTORY_SLOT_CHEST, oTemplate);
ac_info.nArmorBonus = _prc_inc_GetItemACBonus(oArmorItem);
ac_info.nArmorBase = GetItemACValue(oArmorItem) - ac_info.nArmorBonus;
ac_info.nDodgeBonus = GetItemACValue(GetItemInSlot(INVENTORY_SLOT_BOOTS, oTemplate));
ac_info.nNaturalBonus = GetItemACValue(GetItemInSlot(INVENTORY_SLOT_NECK, oTemplate));
ac_info.nDeflectionBonus = GetItemACValue(GetItemInSlot(INVENTORY_SLOT_HEAD, oTemplate));
ac_info.nDeflectionBonus = max(ac_info.nDeflectionBonus, GetItemACValue(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTemplate)));
ac_info.nDeflectionBonus = max(ac_info.nDeflectionBonus, GetItemACValue(GetItemInSlot(INVENTORY_SLOT_CLOAK, oTemplate)));
ac_info.nDeflectionBonus = max(ac_info.nDeflectionBonus, GetItemACValue(GetItemInSlot(INVENTORY_SLOT_RIGHTRING, oTemplate)));
ac_info.nDeflectionBonus = max(ac_info.nDeflectionBonus, GetItemACValue(GetItemInSlot(INVENTORY_SLOT_LEFTRING, oTemplate)));
ac_info.nDeflectionBonus = max(ac_info.nDeflectionBonus, GetItemACValue(GetItemInSlot(INVENTORY_SLOT_BELT, oTemplate)));
ac_info.nDeflectionBonus = max(ac_info.nDeflectionBonus, GetItemACValue(GetItemInSlot(INVENTORY_SLOT_ARROWS, oTemplate)));
ac_info.nDeflectionBonus = max(ac_info.nDeflectionBonus, GetItemACValue(GetItemInSlot(INVENTORY_SLOT_BULLETS, oTemplate)));
ac_info.nDeflectionBonus = max(ac_info.nDeflectionBonus, GetItemACValue(GetItemInSlot(INVENTORY_SLOT_BOLTS, oTemplate)));
ac_info.nDeflectionBonus = max(ac_info.nDeflectionBonus, GetItemACValue(GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oTemplate)));
ac_info.nDeflectionBonus = max(ac_info.nDeflectionBonus, GetItemACValue(GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oTemplate)));
ac_info.nDeflectionBonus = max(ac_info.nDeflectionBonus, GetItemACValue(GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oTemplate)));
ac_info.nDeflectionBonus = max(ac_info.nDeflectionBonus, GetItemACValue(GetItemInSlot(INVENTORY_SLOT_CARMOUR, oTemplate)));
object oOffHandItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTemplate);
ac_info.nShieldBase = 0;
ac_info.nShieldBonus = 0;
switch (GetBaseItemType(oOffHandItem))
{
case BASE_ITEM_SMALLSHIELD:
ac_info.nShieldBase = 1;
ac_info.nShieldBonus = GetItemACValue(oOffHandItem) - ac_info.nShieldBase;
break;
case BASE_ITEM_LARGESHIELD:
ac_info.nShieldBase = 2;
ac_info.nShieldBonus = GetItemACValue(oOffHandItem) - ac_info.nShieldBase;
break;
case BASE_ITEM_TOWERSHIELD:
ac_info.nShieldBase = 3;
ac_info.nShieldBonus = GetItemACValue(oOffHandItem) - ac_info.nShieldBase;
break;
default: //A weapon
ac_info.nDeflectionBonus = max(ac_info.nDeflectionBonus, GetItemACValue(oOffHandItem));
break;
}
object oArmsItem = GetItemInSlot(INVENTORY_SLOT_ARMS, oTemplate);
switch (GetBaseItemType(oArmsItem))
{
case BASE_ITEM_BRACER:
ac_info.nShieldBonus = max(ac_info.nShieldBonus, GetItemACValue(oArmsItem));
break;
case BASE_ITEM_GLOVES:
default:
ac_info.nDeflectionBonus = max(ac_info.nDeflectionBonus, GetItemACValue(oArmsItem));
break;
}
if (ac_info.nArmorBonus > 20)
ac_info.nArmorBonus = 20;
if (ac_info.nDodgeBonus > 20)
ac_info.nDodgeBonus = 20;
if (ac_info.nNaturalBonus > 20)
ac_info.nNaturalBonus = 20;
if (ac_info.nDeflectionBonus > 20)
ac_info.nDeflectionBonus = 20;
if (ac_info.nShieldBonus > 20)
ac_info.nShieldBonus = 20;
ac_info.nDEXBonus = min(GetAbilityModifier(ABILITY_DEXTERITY, oTemplate), _prc_inc_GetArmorMaxDEXBonus(oArmorItem));
//TODO: make sure this isn't < 0?
return ac_info;
}
//Estimate natural AC of the creature oTemplate
int _prc_inc_CreatureNaturalAC(object oTemplate)
{
struct _prc_inc_ac_info_struct ac_info = _prc_inc_ACInfo(oTemplate);
//TODO: GetAC(oTemplate) often returns an AC different (usually higher) than the combat debugging log indicates it should be.
//Note that combat debugging doesn't report DEX bonus, Monk WIS bonus, etc.; where does this come in?
int nNaturalAC = GetAC(oTemplate)
- 10 // Adjust for base AC
- ac_info.nDEXBonus // And Dex bonus
- ac_info.nArmorBase // Etc...
- ac_info.nArmorBonus
- ac_info.nDodgeBonus
- ac_info.nNaturalBonus
- ac_info.nDeflectionBonus
- ac_info.nShieldBase
- ac_info.nShieldBonus;
//TODO:
//Subtract +4 Dodge bonus if template has Haste?
//Subtract +1 AC / each 5 points of the Tumble skill?
//Subtract Monk AC from level progression?
//Subtract WIS AC if Monk/Ninja, etc.?
//Make sure nNaturalAC is not < 0 (it was for me once using the old method of calculation, which is why I created this new one)
if (DEBUG_NATURAL_AC_CALCULATION || DEBUG)
{
DoDebug("_prc_inc_CreatureNaturalAC: total ac: " + IntToString(GetAC(oTemplate)));
DoDebug("_prc_inc_CreatureNaturalAC: base ac: " + IntToString(10));
DoDebug("_prc_inc_CreatureNaturalAC: armor base ac: " + IntToString(ac_info.nArmorBase));
DoDebug("_prc_inc_CreatureNaturalAC: armor bonus ac: " + IntToString(ac_info.nArmorBonus));
DoDebug("_prc_inc_CreatureNaturalAC: shield base ac: " + IntToString(ac_info.nShieldBase));
DoDebug("_prc_inc_CreatureNaturalAC: shield bonus ac: " + IntToString(ac_info.nShieldBonus));
DoDebug("_prc_inc_CreatureNaturalAC: dodge bonus ac: " + IntToString(ac_info.nDodgeBonus));
DoDebug("_prc_inc_CreatureNaturalAC: natural bonus ac: " + IntToString(ac_info.nNaturalBonus));
DoDebug("_prc_inc_CreatureNaturalAC: deflection bonus ac: " + IntToString(ac_info.nDeflectionBonus));
DoDebug("_prc_inc_CreatureNaturalAC: dex ac: " + IntToString(ac_info.nDEXBonus));
DoDebug("_prc_inc_CreatureNaturalAC: calculated natural ac: " + IntToString(nNaturalAC));
}
//TODO: combat debugging shows actual natural AC (as well as other type); compare with that to debug.
return nNaturalAC;
}
int _prc_inc_GetFeatDeathAttackLevel(int nFeat)
{
switch(nFeat)
{
case FEAT_PRESTIGE_DEATH_ATTACK_1: return 1;
case FEAT_PRESTIGE_DEATH_ATTACK_2: return 2;
case FEAT_PRESTIGE_DEATH_ATTACK_3: return 3;
case FEAT_PRESTIGE_DEATH_ATTACK_4: return 4;
case FEAT_PRESTIGE_DEATH_ATTACK_5: return 5;
case FEAT_PRESTIGE_DEATH_ATTACK_6: return 6;
case FEAT_PRESTIGE_DEATH_ATTACK_7: return 7;
case FEAT_PRESTIGE_DEATH_ATTACK_8: return 8;
case FEAT_PRESTIGE_DEATH_ATTACK_9: return 9;
case FEAT_PRESTIGE_DEATH_ATTACK_10: return 10;
case FEAT_PRESTIGE_DEATH_ATTACK_11: return 11;
case FEAT_PRESTIGE_DEATH_ATTACK_12: return 12;
case FEAT_PRESTIGE_DEATH_ATTACK_13: return 13;
case FEAT_PRESTIGE_DEATH_ATTACK_14: return 14;
case FEAT_PRESTIGE_DEATH_ATTACK_15: return 15;
case FEAT_PRESTIGE_DEATH_ATTACK_16: return 16;
case FEAT_PRESTIGE_DEATH_ATTACK_17: return 17;
case FEAT_PRESTIGE_DEATH_ATTACK_18: return 18;
case FEAT_PRESTIGE_DEATH_ATTACK_19: return 19;
case FEAT_PRESTIGE_DEATH_ATTACK_20: return 20;
}
return 0;
}
int _prc_inc_GetHasFeat(object oTemplate, int nFeat)
{
//If oTemplate has the feat FEAT_SNEAK_ATTACK_10, GetHasFeat() always says
//it has FEAT_PRESTIGE_DEATH_ATTACK_1 through FEAT_PRESTIGE_DEATH_ATTACK_20,
//whether it actually does or not. Work around this as follows:
int nSuppress=0;
int FEAT_SNEAK_ATTACK_10 = 353;
if(GetHasFeat(FEAT_SNEAK_ATTACK_10, oTemplate))
{
int nFeatDeathAttackLevel = _prc_inc_GetFeatDeathAttackLevel(nFeat);
if(nFeatDeathAttackLevel)
{
int nActualDeathAttackLevel = 0;
nActualDeathAttackLevel += (GetLevelByClass(CLASS_TYPE_ASSASSIN, oTemplate) + 1) / 2;
//TODO: Add other classes here? OR use GetTotalSneakAttackDice(), etc. from prc_inc_sneak instead?
if(nFeatDeathAttackLevel > nActualDeathAttackLevel)
nSuppress = 1;
}
}
return GetHasFeat(nFeat, oTemplate) && !nSuppress;
}
int _prc_inc_shifting_GetIsCreatureHarmless(object oTemplate)
{
return GetChallengeRating(oTemplate) < 1.0;
}
int _prc_inc_shifting_CharacterLevelRequirement(object oTemplate)
{
return GetPRCSwitch(PNP_SHFT_USECR) ? FloatToInt(GetChallengeRating(oTemplate)) : GetHitDice(oTemplate);
}
int _prc_inc_shifting_ShifterLevelRequirement(object oTemplate)
{
int nRacialType = MyPRCGetRacialType(oTemplate);
int nSize = PRCGetCreatureSize(oTemplate);
int nLevelRequired = 0;
// Size tests
if(nSize >= CREATURE_SIZE_HUGE)
nLevelRequired = max(nLevelRequired, 7);
if(nSize == CREATURE_SIZE_LARGE)
nLevelRequired = max(nLevelRequired, 3);
if(nSize == CREATURE_SIZE_MEDIUM)
nLevelRequired = max(nLevelRequired, 1);
if(nSize == CREATURE_SIZE_SMALL)
nLevelRequired = max(nLevelRequired, 1);
if(nSize <= CREATURE_SIZE_TINY)
nLevelRequired = max(nLevelRequired, 3);
// Type tests
if(nRacialType == RACIAL_TYPE_OUTSIDER)
nLevelRequired = max(nLevelRequired, 9);
if(nRacialType == RACIAL_TYPE_ELEMENTAL)
nLevelRequired = max(nLevelRequired, 9);
if(nRacialType == RACIAL_TYPE_CONSTRUCT)
nLevelRequired = max(nLevelRequired, 8);
if(nRacialType == RACIAL_TYPE_UNDEAD)
nLevelRequired = max(nLevelRequired, 8);
if(nRacialType == RACIAL_TYPE_DRAGON)
nLevelRequired = max(nLevelRequired, 7);
if(nRacialType == RACIAL_TYPE_ABERRATION)
nLevelRequired = max(nLevelRequired, 6);
if(nRacialType == RACIAL_TYPE_OOZE)
nLevelRequired = max(nLevelRequired, 6);
if(nRacialType == RACIAL_TYPE_MAGICAL_BEAST)
nLevelRequired = max(nLevelRequired, 5);
if(nRacialType == RACIAL_TYPE_GIANT)
nLevelRequired = max(nLevelRequired, 4);
if(nRacialType == RACIAL_TYPE_VERMIN)
nLevelRequired = max(nLevelRequired, 4);
if(nRacialType == RACIAL_TYPE_BEAST)
nLevelRequired = max(nLevelRequired, 3);
if(nRacialType == RACIAL_TYPE_ANIMAL)
nLevelRequired = max(nLevelRequired, 2);
if(nRacialType == RACIAL_TYPE_HUMANOID_MONSTROUS)
nLevelRequired = max(nLevelRequired, 2);
if(nRacialType == RACIAL_TYPE_DWARF ||
nRacialType == RACIAL_TYPE_ELF ||
nRacialType == RACIAL_TYPE_GNOME ||
nRacialType == RACIAL_TYPE_HUMAN ||
nRacialType == RACIAL_TYPE_HALFORC ||
nRacialType == RACIAL_TYPE_HALFELF ||
nRacialType == RACIAL_TYPE_HALFLING ||
nRacialType == RACIAL_TYPE_HUMANOID_ORC ||
nRacialType == RACIAL_TYPE_HUMANOID_REPTILIAN
)
nLevelRequired = max(nLevelRequired, 1);
return nLevelRequired;
}
int _prc_inc_shifting_GetCanFormCast(object oTemplate)
{
int nRacialType = MyPRCGetRacialType(oTemplate);
// Need to have hands, and the ability to speak
switch (nRacialType)
{
case RACIAL_TYPE_ABERRATION:
case RACIAL_TYPE_ANIMAL:
case RACIAL_TYPE_BEAST:
case RACIAL_TYPE_MAGICAL_BEAST:
case RACIAL_TYPE_VERMIN:
case RACIAL_TYPE_OOZE:
// case RACIAL_TYPE_PLANT:
// These forms can't cast spells
return FALSE;
case RACIAL_TYPE_DWARF:
case RACIAL_TYPE_ELF:
case RACIAL_TYPE_GNOME:
case RACIAL_TYPE_HALFLING:
case RACIAL_TYPE_HALFELF:
case RACIAL_TYPE_HALFORC:
case RACIAL_TYPE_HUMAN:
case RACIAL_TYPE_CONSTRUCT:
case RACIAL_TYPE_DRAGON:
case RACIAL_TYPE_HUMANOID_GOBLINOID:
case RACIAL_TYPE_HUMANOID_MONSTROUS:
case RACIAL_TYPE_HUMANOID_ORC:
case RACIAL_TYPE_HUMANOID_REPTILIAN:
case RACIAL_TYPE_ELEMENTAL:
case RACIAL_TYPE_FEY:
case RACIAL_TYPE_GIANT:
case RACIAL_TYPE_OUTSIDER:
case RACIAL_TYPE_SHAPECHANGER:
case RACIAL_TYPE_UNDEAD:
// Break and go return TRUE at the end of the function
break;
default:{
if(DEBUG) DoDebug("prc_inc_shifting: _GetCanFormCast(): Unknown racial type: " + IntToString(nRacialType));
}
}
return TRUE;
}
string _prc_inc_AbilityTypeString(int nAbilityType)
{
return GetStringByStrRef(StringToInt(Get2DACache("iprp_abilities", "Name", nAbilityType)));
}
string _prc_inc_AlignmentGroupString(int nAlignmentGroup)
{
return GetStringByStrRef(StringToInt(Get2DACache("iprp_aligngrp", "Name", nAlignmentGroup)));
}
string _prc_inc_BonusFeatTypeString(int nBonusFeatType)
{
return GetStringByStrRef(StringToInt(Get2DACache("iprp_feats", "Name", nBonusFeatType)));
}
string _prc_inc_ClassTypeString(int nClassType)
{
return GetStringByStrRef(StringToInt(Get2DACache("classes", "Name", nClassType)));
}
string _prc_inc_CostTableEntryString(int nCostTable, int nCostTableValue)
{
string sCostTableName = Get2DACache("iprp_costtable", "Name", nCostTable);
if(sCostTableName == "" || sCostTableName == "****")
return "??? (" + IntToString(nCostTable) + " / " + IntToString(nCostTableValue) + ")";
string sCostTableEntry = Get2DACache(sCostTableName, "Name", nCostTableValue);
if(sCostTableEntry == "" || sCostTableEntry == "****")
return "??? (" + sCostTableName + " / " + IntToString(nCostTableValue) + ")";
return GetStringByStrRef(StringToInt(sCostTableEntry));
}
string _prc_inc_DamageTypeString(int nDamageType)
{
return GetStringByStrRef(StringToInt(Get2DACache("iprp_damagetype", "Name", nDamageType)));
}
string _prc_inc_ImmunityTypeString(int nImmunityType)
{
return GetStringByStrRef(StringToInt(Get2DACache("iprp_immunity", "Name", nImmunityType)));
}
string _prc_inc_OnHitSpellTypeString(int nOnHitSpellType)
{
return GetStringByStrRef(StringToInt(Get2DACache("iprp_onhitspell", "Name", nOnHitSpellType)));
}
string _prc_inc_OnHitTypeString(int nOnHitSpellType)
{
return GetStringByStrRef(StringToInt(Get2DACache("iprp_onhit", "Name", nOnHitSpellType)));
}
string _prc_inc_OnMonsterHitTypeString(int nOnMonsterHitType)
{
return GetStringByStrRef(StringToInt(Get2DACache("iprp_monsterhit", "Name", nOnMonsterHitType)));
}
string _prc_inc_SavingThrowElementTypeString(int nSavingThrowType)
{
return GetStringByStrRef(StringToInt(Get2DACache("iprp_saveelement", "Name", nSavingThrowType)));
}
string _prc_inc_SavingThrowTypeString(int nSavingThrowType)
{
return GetStringByStrRef(StringToInt(Get2DACache("iprp_savingthrow", "Name", nSavingThrowType)));
}
string _prc_inc_SkillTypeString(int nSkillType)
{
return GetStringByStrRef(StringToInt(Get2DACache("skills", "Name", nSkillType)));
}
string _prc_inc_SpecialWalkTypeString(int nWalkType)
{
return GetStringByStrRef(StringToInt(Get2DACache("iprp_walk", "Name", nWalkType)));
}
string _prc_inc_SpellSchoolTypeString(int nSpellSchoolType)
{
return GetStringByStrRef(StringToInt(Get2DACache("iprp_spellshl", "Name", nSpellSchoolType)));
}
string _prc_inc_SpellTypeString(int nOnHitSpellType)
{
return GetStringByStrRef(StringToInt(Get2DACache("iprp_spells", "Name", nOnHitSpellType)));
}
string _prc_inc_VisualEffectString(int nVisualEffect)
{
//TODO: Look up in 2da (which one?)
switch(nVisualEffect)
{
case ITEM_VISUAL_ACID:
return "Acid";
case ITEM_VISUAL_COLD:
return "Cold";
case ITEM_VISUAL_ELECTRICAL:
return "Electrical";
case ITEM_VISUAL_FIRE:
return "Fire";
case ITEM_VISUAL_SONIC:
return "Sonic";
case ITEM_VISUAL_HOLY:
return "Holy";
case ITEM_VISUAL_EVIL:
return "Evil";
}
return "???";
}
string _prc_inc_ItemPropertyString(itemproperty iprop)
{
int nType = GetItemPropertyType(iprop);
int nSubType = GetItemPropertySubType(iprop);
int nDurationType = GetItemPropertyDurationType(iprop);
int nParam1 = GetItemPropertyParam1(iprop);
int nParam1Value = GetItemPropertyParam1Value(iprop);
int nCostTable = GetItemPropertyCostTable(iprop);
int nCostTableValue = GetItemPropertyCostTableValue(iprop);
string sType = IntToString(nType);
string sSubType = IntToString(nSubType);
string sDurationType = IntToString(nDurationType);
string sParam1 = IntToString(nParam1);
string sParam1Value = IntToString(nParam1Value);
string sCostTable = IntToString(nCostTable);
string sCostTableValue = IntToString(nCostTableValue);
string sResult =
"Typ: " + sType + "; "
+ "SubTyp: " + sSubType + "; "
+ "DurTyp: " + sDurationType + "; "
+ "Parm: " + sParam1 + "; "
+ "ParmVal: " + sParam1Value + "; "
+ "CTab: " + sCostTable + "; "
+ "CVal: " + sCostTableValue;
string sTypeName = GetStringByStrRef(StringToInt(Get2DACache("itempropdef", "Name", nType)));
switch (nType)
{
//TODO: these are all the possible cases; need to handle more of them.
//DONE case ITEM_PROPERTY_ABILITY_BONUS:
//DONE case ITEM_PROPERTY_AC_BONUS:
// case ITEM_PROPERTY_AC_BONUS_VS_ALIGNMENT_GROUP:
// case ITEM_PROPERTY_AC_BONUS_VS_DAMAGE_TYPE:
// case ITEM_PROPERTY_AC_BONUS_VS_RACIAL_GROUP:
// case ITEM_PROPERTY_AC_BONUS_VS_SPECIFIC_ALIGNMENT:
//DONE case ITEM_PROPERTY_ENHANCEMENT_BONUS:
//DONE case ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_ALIGNMENT_GROUP:
// case ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_RACIAL_GROUP:
// case ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_SPECIFIC_ALIGNEMENT:
// case ITEM_PROPERTY_DECREASED_ENHANCEMENT_MODIFIER
//DONE case ITEM_PROPERTY_BASE_ITEM_WEIGHT_REDUCTION
//DONE case ITEM_PROPERTY_BONUS_FEAT:
// case ITEM_PROPERTY_BONUS_SPELL_SLOT_OF_LEVEL_N:
//DONE case ITEM_PROPERTY_CAST_SPELL:
//DONE case ITEM_PROPERTY_DAMAGE_BONUS:
//DONE case ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP:
//case ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP:
//case ITEM_PROPERTY_DAMAGE_BONUS_VS_SPECIFIC_ALIGNMENT:
//DONE case ITEM_PROPERTY_IMMUNITY_DAMAGE_TYPE:
// case ITEM_PROPERTY_DECREASED_DAMAGE:
//DONE case ITEM_PROPERTY_DAMAGE_REDUCTION:
//DONE case ITEM_PROPERTY_DAMAGE_RESISTANCE:
//DONE case ITEM_PROPERTY_DAMAGE_VULNERABILITY:
//DONE case ITEM_PROPERTY_DARKVISION:
//DONE case ITEM_PROPERTY_DECREASED_ABILITY_SCORE:
// case ITEM_PROPERTY_DECREASED_AC:
// case ITEM_PROPERTY_DECREASED_SKILL_MODIFIER: //TODO: e.g. S1-Tomb of Horrors: DesertDragon
// case ITEM_PROPERTY_ENHANCED_CONTAINER_REDUCED_WEIGHT:
//DONE case ITEM_PROPERTY_EXTRA_MELEE_DAMAGE_TYPE:
// case ITEM_PROPERTY_EXTRA_RANGED_DAMAGE_TYPE:
//DONE case ITEM_PROPERTY_HASTE:
// case ITEM_PROPERTY_HOLY_AVENGER:
//DONE case ITEM_PROPERTY_IMMUNITY_MISCELLANEOUS:
//DONE case ITEM_PROPERTY_IMPROVED_EVASION:
//DONE case ITEM_PROPERTY_SPELL_RESISTANCE:
//DONE case ITEM_PROPERTY_SAVING_THROW_BONUS:
//DONE case ITEM_PROPERTY_SAVING_THROW_BONUS_SPECIFIC:
//DONE case ITEM_PROPERTY_KEEN:
//DONE case ITEM_PROPERTY_LIGHT:
// case ITEM_PROPERTY_MIGHTY:
// case ITEM_PROPERTY_MIND_BLANK:
// case ITEM_PROPERTY_NO_DAMAGE:
//DONE case ITEM_PROPERTY_ON_HIT_PROPERTIES:
//DONE case ITEM_PROPERTY_DECREASED_SAVING_THROWS:
//DONE case ITEM_PROPERTY_DECREASED_SAVING_THROWS_SPECIFIC:
//DONE case ITEM_PROPERTY_REGENERATION:
//DONE case ITEM_PROPERTY_SKILL_BONUS:
//DONE case ITEM_PROPERTY_IMMUNITY_SPECIFIC_SPELL:
//DONE case ITEM_PROPERTY_IMMUNITY_SPELL_SCHOOL:
// case ITEM_PROPERTY_THIEVES_TOOLS:
//DONE case ITEM_PROPERTY_ATTACK_BONUS:
//DONE case ITEM_PROPERTY_ATTACK_BONUS_VS_ALIGNMENT_GROUP:
// case ITEM_PROPERTY_ATTACK_BONUS_VS_RACIAL_GROUP:
// case ITEM_PROPERTY_ATTACK_BONUS_VS_SPECIFIC_ALIGNMENT:
// case ITEM_PROPERTY_DECREASED_ATTACK_MODIFIER:
// case ITEM_PROPERTY_UNLIMITED_AMMUNITION:
// case ITEM_PROPERTY_USE_LIMITATION_ALIGNMENT_GROUP:
// case ITEM_PROPERTY_USE_LIMITATION_CLASS:
// case ITEM_PROPERTY_USE_LIMITATION_RACIAL_TYPE:
// case ITEM_PROPERTY_USE_LIMITATION_SPECIFIC_ALIGNMENT:
// case ITEM_PROPERTY_USE_LIMITATION_TILESET:
//DONE case ITEM_PROPERTY_REGENERATION_VAMPIRIC:
// case ITEM_PROPERTY_TRAP:
//DONE case ITEM_PROPERTY_TRUE_SEEING:
//DONE case ITEM_PROPERTY_ON_MONSTER_HIT:
//DONE case ITEM_PROPERTY_TURN_RESISTANCE:
//DONE case ITEM_PROPERTY_MASSIVE_CRITICALS:
//DONE case ITEM_PROPERTY_FREEDOM_OF_MOVEMENT:
//DONE case ITEM_PROPERTY_MONSTER_DAMAGE:
//DONE case ITEM_PROPERTY_IMMUNITY_SPELLS_BY_LEVEL:
//DONE case ITEM_PROPERTY_SPECIAL_WALK:
// case ITEM_PROPERTY_HEALERS_KIT:
// case ITEM_PROPERTY_WEIGHT_INCREASE:
//DONE case ITEM_PROPERTY_ONHITCASTSPELL:
//DONE case ITEM_PROPERTY_VISUALEFFECT:
// case ITEM_PROPERTY_ARCANE_SPELL_FAILURE:
//Completely ignore
case ITEM_PROPERTY_BASE_ITEM_WEIGHT_REDUCTION:
return "";
//Property name only
case ITEM_PROPERTY_DARKVISION:
case ITEM_PROPERTY_FREEDOM_OF_MOVEMENT:
case ITEM_PROPERTY_HASTE:
case ITEM_PROPERTY_IMPROVED_EVASION:
case ITEM_PROPERTY_KEEN:
case ITEM_PROPERTY_TRUE_SEEING:
return sTypeName;
//Interpret cost table information
case ITEM_PROPERTY_AC_BONUS:
case ITEM_PROPERTY_ATTACK_BONUS:
case ITEM_PROPERTY_ENHANCEMENT_BONUS:
case ITEM_PROPERTY_IMMUNITY_SPECIFIC_SPELL:
case ITEM_PROPERTY_IMMUNITY_SPELLS_BY_LEVEL:
case ITEM_PROPERTY_LIGHT:
case ITEM_PROPERTY_MASSIVE_CRITICALS:
case ITEM_PROPERTY_MONSTER_DAMAGE:
case ITEM_PROPERTY_REGENERATION:
case ITEM_PROPERTY_SPELL_RESISTANCE:
case ITEM_PROPERTY_TURN_RESISTANCE:
return sTypeName + ": " + _prc_inc_CostTableEntryString(nCostTable, nCostTableValue);
//Interpret cost table information; interpret subtype as damage type
case ITEM_PROPERTY_DAMAGE_BONUS:
case ITEM_PROPERTY_DAMAGE_RESISTANCE:
case ITEM_PROPERTY_DAMAGE_VULNERABILITY:
case ITEM_PROPERTY_IMMUNITY_DAMAGE_TYPE:
return sTypeName + ": " + _prc_inc_CostTableEntryString(nCostTable, nCostTableValue) + " " + _prc_inc_DamageTypeString(nSubType);
//Interpret cost table information; interpret subtype as racial group
case ITEM_PROPERTY_ATTACK_BONUS_VS_ALIGNMENT_GROUP:
case ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_ALIGNMENT_GROUP:
return sTypeName + ": " + _prc_inc_AlignmentGroupString(nSubType) + " " + _prc_inc_CostTableEntryString(nCostTable, nCostTableValue);
//Special handling
case ITEM_PROPERTY_ABILITY_BONUS:
case ITEM_PROPERTY_DECREASED_ABILITY_SCORE:
return sTypeName + ": " + _prc_inc_AbilityTypeString(nSubType) + " " + _prc_inc_CostTableEntryString(nCostTable, nCostTableValue);
case ITEM_PROPERTY_BONUS_FEAT:
return sTypeName + ": " + _prc_inc_BonusFeatTypeString(nSubType);
case ITEM_PROPERTY_CAST_SPELL:
return sTypeName + ": " + _prc_inc_SpellTypeString(nSubType) + " " + _prc_inc_CostTableEntryString(nCostTable, nCostTableValue);
case ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP:
return sTypeName + ": " + _prc_inc_AlignmentGroupString(nSubType) + " " + _prc_inc_CostTableEntryString(nCostTable, nCostTableValue) + " " + _prc_inc_DamageTypeString(nParam1Value);
case ITEM_PROPERTY_DAMAGE_REDUCTION:
return sTypeName + ": " + _prc_inc_CostTableEntryString(nCostTable, nCostTableValue) + " / " + IntToString(StringToInt(sSubType)+1);
case ITEM_PROPERTY_EXTRA_MELEE_DAMAGE_TYPE:
case ITEM_PROPERTY_EXTRA_RANGED_DAMAGE_TYPE:
return sTypeName + ": " + _prc_inc_DamageTypeString(nSubType);
case ITEM_PROPERTY_IMMUNITY_MISCELLANEOUS:
return sTypeName + ": " + _prc_inc_ImmunityTypeString(nSubType);
case ITEM_PROPERTY_IMMUNITY_SPELL_SCHOOL:
return sTypeName + ": " + _prc_inc_SpellSchoolTypeString(nSubType);
case ITEM_PROPERTY_ON_HIT_PROPERTIES:
return sTypeName + ": " + _prc_inc_OnHitTypeString(nSubType) + " " + _prc_inc_CostTableEntryString(nCostTable, nCostTableValue);
case ITEM_PROPERTY_ONHITCASTSPELL:
return sTypeName + ": " + _prc_inc_OnHitSpellTypeString(nSubType) + " " + _prc_inc_CostTableEntryString(nCostTable, nCostTableValue);
case ITEM_PROPERTY_ON_MONSTER_HIT:
return sTypeName + ": " + _prc_inc_OnMonsterHitTypeString(nSubType) + " " + IntToString(nCostTableValue+1);
case ITEM_PROPERTY_SKILL_BONUS:
return sTypeName + ": " + _prc_inc_SkillTypeString(nSubType) + " " + _prc_inc_CostTableEntryString(nCostTable, nCostTableValue);
case ITEM_PROPERTY_SPECIAL_WALK:
return sTypeName + ": " + _prc_inc_SpecialWalkTypeString(nSubType);
case ITEM_PROPERTY_REGENERATION_VAMPIRIC:
return sTypeName + ": " + _prc_inc_CostTableEntryString(nCostTable, nCostTableValue);
case ITEM_PROPERTY_VISUALEFFECT:
return sTypeName + ": " + _prc_inc_VisualEffectString(nSubType);
case ITEM_PROPERTY_DECREASED_SAVING_THROWS_SPECIFIC:
case ITEM_PROPERTY_SAVING_THROW_BONUS_SPECIFIC:
return sTypeName + ": " + _prc_inc_SavingThrowTypeString(nSubType) + " " + _prc_inc_CostTableEntryString(nCostTable, nCostTableValue);
case ITEM_PROPERTY_DECREASED_SAVING_THROWS:
case ITEM_PROPERTY_SAVING_THROW_BONUS:
return sTypeName + ": " + _prc_inc_SavingThrowElementTypeString(nSubType) + " " + _prc_inc_CostTableEntryString(nCostTable, nCostTableValue);
}
return sTypeName + " (" + sResult + ")";
}
string _prc_inc_EffectString(effect eEffect)
{
int nType = GetEffectType(eEffect);
int nSubType = GetEffectSubType(eEffect);
int nDurationType = GetEffectDurationType(eEffect);
int nSpellId = GetEffectSpellId(eEffect);
string sType = IntToString(nType);
string sSubType = IntToString(nSubType);
string sDurationType = IntToString(nDurationType);
string sSpellId = IntToString(nSpellId);
//Decode type if possible
//TODO: look up in 2da (which one?) instead of having a big switch statement
switch (nType)
{
case EFFECT_TYPE_INVALIDEFFECT : sType = "EFFECT_TYPE_INVALIDEFFECT"; break;
case EFFECT_TYPE_DAMAGE_RESISTANCE : sType = "EFFECT_TYPE_DAMAGE_RESISTANCE"; break;
//case EFFECT_TYPE_ABILITY_BONUS : sType = "EFFECT_TYPE_ABILITY_BONUS"; break;
case EFFECT_TYPE_REGENERATE : sType = "EFFECT_TYPE_REGENERATE"; break;
//case EFFECT_TYPE_SAVING_THROW_BONUS : sType = "EFFECT_TYPE_SAVING_THROW_BONUS"; break;
//case EFFECT_TYPE_MODIFY_AC : sType = "EFFECT_TYPE_MODIFY_AC"; break;
//case EFFECT_TYPE_ATTACK_BONUS : sType = "EFFECT_TYPE_ATTACK_BONUS"; break;
case EFFECT_TYPE_DAMAGE_REDUCTION : sType = "EFFECT_TYPE_DAMAGE_REDUCTION"; break;
//case EFFECT_TYPE_DAMAGE_BONUS : sType = "EFFECT_TYPE_DAMAGE_BONUS"; break;
case EFFECT_TYPE_TEMPORARY_HITPOINTS : sType = "EFFECT_TYPE_TEMPORARY_HITPOINTS"; break;
//case EFFECT_TYPE_DAMAGE_IMMUNITY : sType = "EFFECT_TYPE_DAMAGE_IMMUNITY"; break;
case EFFECT_TYPE_ENTANGLE : sType = "EFFECT_TYPE_ENTANGLE"; break;
case EFFECT_TYPE_INVULNERABLE : sType = "EFFECT_TYPE_INVULNERABLE"; break;
case EFFECT_TYPE_DEAF : sType = "EFFECT_TYPE_DEAF"; break;
case EFFECT_TYPE_RESURRECTION : sType = "EFFECT_TYPE_RESURRECTION"; break;
case EFFECT_TYPE_IMMUNITY : sType = "EFFECT_TYPE_IMMUNITY"; break;
//case EFFECT_TYPE_BLIND : sType = "EFFECT_TYPE_BLIND"; break;
case EFFECT_TYPE_ENEMY_ATTACK_BONUS : sType = "EFFECT_TYPE_ENEMY_ATTACK_BONUS"; break;
case EFFECT_TYPE_ARCANE_SPELL_FAILURE : sType = "EFFECT_TYPE_ARCANE_SPELL_FAILURE"; break;
//case EFFECT_TYPE_MOVEMENT_SPEED : sType = "EFFECT_TYPE_MOVEMENT_SPEED"; break;
case EFFECT_TYPE_AREA_OF_EFFECT : sType = "EFFECT_TYPE_AREA_OF_EFFECT"; break;
case EFFECT_TYPE_BEAM : sType = "EFFECT_TYPE_BEAM"; break;
//case EFFECT_TYPE_SPELL_RESISTANCE : sType = "EFFECT_TYPE_SPELL_RESISTANCE"; break;
case EFFECT_TYPE_CHARMED : sType = "EFFECT_TYPE_CHARMED"; break;
case EFFECT_TYPE_CONFUSED : sType = "EFFECT_TYPE_CONFUSED"; break;
case EFFECT_TYPE_FRIGHTENED : sType = "EFFECT_TYPE_FRIGHTENED"; break;
case EFFECT_TYPE_DOMINATED : sType = "EFFECT_TYPE_DOMINATED"; break;
case EFFECT_TYPE_PARALYZE : sType = "EFFECT_TYPE_PARALYZE"; break;
case EFFECT_TYPE_DAZED : sType = "EFFECT_TYPE_DAZED"; break;
case EFFECT_TYPE_STUNNED : sType = "EFFECT_TYPE_STUNNED"; break;
case EFFECT_TYPE_SLEEP : sType = "EFFECT_TYPE_SLEEP"; break;
case EFFECT_TYPE_POISON : sType = "EFFECT_TYPE_POISON"; break;
case EFFECT_TYPE_DISEASE : sType = "EFFECT_TYPE_DISEASE"; break;
case EFFECT_TYPE_CURSE : sType = "EFFECT_TYPE_CURSE"; break;
case EFFECT_TYPE_SILENCE : sType = "EFFECT_TYPE_SILENCE"; break;
case EFFECT_TYPE_TURNED : sType = "EFFECT_TYPE_TURNED"; break;
case EFFECT_TYPE_HASTE : sType = "EFFECT_TYPE_HASTE"; break;
case EFFECT_TYPE_SLOW : sType = "EFFECT_TYPE_SLOW"; break;
case EFFECT_TYPE_ABILITY_INCREASE : sType = "EFFECT_TYPE_ABILITY_INCREASE"; break;
case EFFECT_TYPE_ABILITY_DECREASE : sType = "EFFECT_TYPE_ABILITY_DECREASE"; break;
case EFFECT_TYPE_ATTACK_INCREASE : sType = "EFFECT_TYPE_ATTACK_INCREASE"; break;
case EFFECT_TYPE_ATTACK_DECREASE : sType = "EFFECT_TYPE_ATTACK_DECREASE"; break;
case EFFECT_TYPE_DAMAGE_INCREASE : sType = "EFFECT_TYPE_DAMAGE_INCREASE"; break;
case EFFECT_TYPE_DAMAGE_DECREASE : sType = "EFFECT_TYPE_DAMAGE_DECREASE"; break;
case EFFECT_TYPE_DAMAGE_IMMUNITY_INCREASE : sType = "EFFECT_TYPE_DAMAGE_IMMUNITY_INCREASE"; break;
case EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE : sType = "EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE"; break;
case EFFECT_TYPE_AC_INCREASE : sType = "EFFECT_TYPE_AC_INCREASE"; break;
case EFFECT_TYPE_AC_DECREASE : sType = "EFFECT_TYPE_AC_DECREASE"; break;
case EFFECT_TYPE_MOVEMENT_SPEED_INCREASE : sType = "EFFECT_TYPE_MOVEMENT_SPEED_INCREASE"; break;
case EFFECT_TYPE_MOVEMENT_SPEED_DECREASE : sType = "EFFECT_TYPE_MOVEMENT_SPEED_DECREASE"; break;
case EFFECT_TYPE_SAVING_THROW_INCREASE : sType = "EFFECT_TYPE_SAVING_THROW_INCREASE"; break;
case EFFECT_TYPE_SAVING_THROW_DECREASE : sType = "EFFECT_TYPE_SAVING_THROW_DECREASE"; break;
case EFFECT_TYPE_SPELL_RESISTANCE_INCREASE : sType = "EFFECT_TYPE_SPELL_RESISTANCE_INCREASE"; break;
case EFFECT_TYPE_SPELL_RESISTANCE_DECREASE : sType = "EFFECT_TYPE_SPELL_RESISTANCE_DECREASE"; break;
case EFFECT_TYPE_SKILL_INCREASE : sType = "EFFECT_TYPE_SKILL_INCREASE"; break;
case EFFECT_TYPE_SKILL_DECREASE : sType = "EFFECT_TYPE_SKILL_DECREASE"; break;
case EFFECT_TYPE_INVISIBILITY : sType = "EFFECT_TYPE_INVISIBILITY"; break;
case EFFECT_TYPE_IMPROVEDINVISIBILITY : sType = "EFFECT_TYPE_IMPROVEDINVISIBILITY"; break;
case EFFECT_TYPE_DARKNESS : sType = "EFFECT_TYPE_DARKNESS"; break;
case EFFECT_TYPE_DISPELMAGICALL : sType = "EFFECT_TYPE_DISPELMAGICALL"; break;
case EFFECT_TYPE_ELEMENTALSHIELD : sType = "EFFECT_TYPE_ELEMENTALSHIELD"; break;
case EFFECT_TYPE_NEGATIVELEVEL : sType = "EFFECT_TYPE_NEGATIVELEVEL"; break;
case EFFECT_TYPE_POLYMORPH : sType = "EFFECT_TYPE_POLYMORPH"; break;
case EFFECT_TYPE_SANCTUARY : sType = "EFFECT_TYPE_SANCTUARY"; break;
case EFFECT_TYPE_TRUESEEING : sType = "EFFECT_TYPE_TRUESEEING"; break;
case EFFECT_TYPE_SEEINVISIBLE : sType = "EFFECT_TYPE_SEEINVISIBLE"; break;
case EFFECT_TYPE_TIMESTOP : sType = "EFFECT_TYPE_TIMESTOP"; break;
case EFFECT_TYPE_BLINDNESS : sType = "EFFECT_TYPE_BLINDNESS"; break;
case EFFECT_TYPE_SPELLLEVELABSORPTION : sType = "EFFECT_TYPE_SPELLLEVELABSORPTION"; break;
case EFFECT_TYPE_DISPELMAGICBEST : sType = "EFFECT_TYPE_DISPELMAGICBEST"; break;
case EFFECT_TYPE_ULTRAVISION : sType = "EFFECT_TYPE_ULTRAVISION"; break;
case EFFECT_TYPE_MISS_CHANCE : sType = "EFFECT_TYPE_MISS_CHANCE"; break;
case EFFECT_TYPE_CONCEALMENT : sType = "EFFECT_TYPE_CONCEALMENT"; break;
case EFFECT_TYPE_SPELL_IMMUNITY : sType = "EFFECT_TYPE_SPELL_IMMUNITY"; break;
case EFFECT_TYPE_VISUALEFFECT : sType = "EFFECT_TYPE_VISUALEFFECT"; break;
case EFFECT_TYPE_DISAPPEARAPPEAR : sType = "EFFECT_TYPE_DISAPPEARAPPEAR"; break;
case EFFECT_TYPE_SWARM : sType = "EFFECT_TYPE_SWARM"; break;
case EFFECT_TYPE_TURN_RESISTANCE_DECREASE : sType = "EFFECT_TYPE_TURN_RESISTANCE_DECREASE"; break;
case EFFECT_TYPE_TURN_RESISTANCE_INCREASE : sType = "EFFECT_TYPE_TURN_RESISTANCE_INCREASE"; break;
case EFFECT_TYPE_PETRIFY : sType = "EFFECT_TYPE_PETRIFY"; break;
case EFFECT_TYPE_CUTSCENE_PARALYZE : sType = "EFFECT_TYPE_CUTSCENE_PARALYZE"; break;
case EFFECT_TYPE_ETHEREAL : sType = "EFFECT_TYPE_ETHEREAL"; break;
case EFFECT_TYPE_SPELL_FAILURE : sType = "EFFECT_TYPE_SPELL_FAILURE"; break;
case EFFECT_TYPE_CUTSCENEGHOST : sType = "EFFECT_TYPE_CUTSCENEGHOST"; break;
case EFFECT_TYPE_CUTSCENEIMMOBILIZE : sType = "EFFECT_TYPE_CUTSCENEIMMOBILIZE"; break;
}
//Decode subtype if possible
//TODO: look up in 2da (which one?) instead of having a switch statement
switch (nSubType)
{
case SUBTYPE_MAGICAL : sSubType = "SUBTYPE_MAGICAL"; break;
case SUBTYPE_SUPERNATURAL : sSubType = "SUBTYPE_SUPERNATURAL"; break;
case SUBTYPE_EXTRAORDINARY : sSubType = "SUBTYPE_EXTRAORDINARY"; break;
}
//Decode duration type if possible
//TODO: look up in 2da (which one?) instead of having a switch statement
switch (nDurationType)
{
case DURATION_TYPE_INSTANT : sDurationType = "DURATION_TYPE_INSTANT"; break;
case DURATION_TYPE_TEMPORARY : sDurationType = "DURATION_TYPE_TEMPORARY"; break;
case DURATION_TYPE_PERMANENT : sDurationType = "DURATION_TYPE_PERMANENT"; break;
}
string sResult =
"EFFECT Type: " + sType + "; "
+ "SubType: " + sSubType + "; "
+ "DurationType: " + sDurationType + "; "
+ "SpellId: " + sSpellId;
return sResult;
}
void _prc_inc_PrintShapeInfo(object oPC, string sMessage)
{
if(!GetLocalInt(oPC, "PRC_SuppressChatPrint"))
SendMessageToPC(oPC, sMessage); //Send to chat window in game
if(GetLocalInt(oPC, "PRC_EnableLogPrint"))
PrintString(sMessage); //Write to log file for reference
}
void _prc_inc_PrintClassInfo(string sPrefix, object oPC, object oTemplate, int nClassType)
{
if (nClassType != CLASS_TYPE_INVALID)
{
int nLevel = GetLevelByClass(nClassType, oTemplate);
string sClassName = _prc_inc_ClassTypeString(nClassType);
_prc_inc_PrintShapeInfo(oPC, sPrefix + sClassName + " (" + IntToString(nLevel) + ")");
}
}
void _prc_inc_PrintItemProperty(string sPrefix, object oPC, itemproperty iProp, int bIncludeTemp = FALSE)
{
int nDurationType = GetItemPropertyDurationType(iProp);
if(nDurationType == DURATION_TYPE_PERMANENT || (bIncludeTemp && nDurationType == DURATION_TYPE_TEMPORARY))
{
string sPropString = _prc_inc_ItemPropertyString(iProp);
if(sPropString != "")
{
if (nDurationType == DURATION_TYPE_TEMPORARY)
sPropString = GetStringByStrRef(57473+0x01000000) + sPropString; //"TEMPORARY: "
_prc_inc_PrintShapeInfo(oPC, sPrefix + sPropString);
}
}
}
void _prc_inc_PrintAllItemProperties(string sPrefix, object oPC, object oItem, int bIncludeTemp = FALSE)
{
itemproperty iProp = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(iProp))
{
_prc_inc_PrintItemProperty(sPrefix, oPC, iProp, bIncludeTemp);
iProp = GetNextItemProperty(oItem);
}
}
void _prc_inc_PrintEffect(string sPrefix, object oPC, effect eEffect)
{
if (GetEffectType(eEffect) == EFFECT_TYPE_INVALIDEFFECT)
{
//An effect with type EFFECT_TYPE_INVALID is added for each item property
//They are also added for a couple of other things (Knockdown, summons, etc.)
//Just skip these
}
else
{
string sEffectString = _prc_inc_EffectString(eEffect);
if(sEffectString != "")
_prc_inc_PrintShapeInfo(oPC, sPrefix + sEffectString);
}
}
void _prc_inc_PrintAllEffects(string sPrefix, object oPC, object oItem)
{
effect eEffect = GetFirstEffect(oItem);
while(GetIsEffectValid(eEffect))
{
_prc_inc_PrintEffect(sPrefix, oPC, eEffect);
eEffect = GetNextEffect(oItem);
}
}
//NOTE: THIS FUNCTION HAS A LOT OF CODE IN COMMON WITH _prc_inc_shifting_CreateShifterActiveAbilitiesItem
//TODO: PUT SOME OF IT IN A SHARED FUNCTION THAT THEY BOTH CALL
void _prc_inc_shifting_PrintShifterActiveAbilities(object oPC, object oTemplate)
{
string sPrefix = GetStringByStrRef(57437+0x01000000); //"Epic Wildshape Spell-Like Abilities:"
_prc_inc_PrintShapeInfo(oPC, "=== " + sPrefix);
int bPrinted = FALSE;
object oTemplateHide = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oTemplate);
itemproperty iProp = GetFirstItemProperty(oTemplateHide);
while(GetIsItemPropertyValid(iProp))
{
if(GetItemPropertyDurationType(iProp) == DURATION_TYPE_PERMANENT && GetItemPropertyType(iProp) == ITEM_PROPERTY_CAST_SPELL)
{
_prc_inc_PrintItemProperty("=== ", oPC, iProp);
bPrinted = TRUE;
}
iProp = GetNextItemProperty(oTemplateHide);
}
// Loop over shifter_abilitie.2da
string sNumUses;
int nSpell, nNumUses, nProps;
int i = 0;
while(nSpell = StringToInt(Get2DACache("shifter_abilitie", "Spell", i)))
{
// See if the template has this spell
if(GetHasSpell(nSpell, oTemplate))
{
// Determine the number of uses from the 2da
sNumUses = Get2DACache("shifter_abilitie", "IPCSpellNumUses", i);
if(sNumUses == "1_USE_PER_DAY")
nNumUses = IP_CONST_CASTSPELL_NUMUSES_1_USE_PER_DAY;
else if(sNumUses == "2_USES_PER_DAY")
nNumUses = IP_CONST_CASTSPELL_NUMUSES_2_USES_PER_DAY;
else if(sNumUses == "3_USES_PER_DAY")
nNumUses = IP_CONST_CASTSPELL_NUMUSES_3_USES_PER_DAY;
else if(sNumUses == "4_USES_PER_DAY")
nNumUses = IP_CONST_CASTSPELL_NUMUSES_4_USES_PER_DAY;
else if(sNumUses == "5_USES_PER_DAY")
nNumUses = IP_CONST_CASTSPELL_NUMUSES_5_USES_PER_DAY;
else if(sNumUses == "UNLIMITED_USE")
nNumUses = IP_CONST_CASTSPELL_NUMUSES_UNLIMITED_USE;
else{
if(DEBUG) DoDebug("prc_inc_shifting: _prc_inc_shifting_PrintShifterActiveAbilities(): Unknown IPCSpellNumUses in shifter_abilitie.2da line " + IntToString(i) + ": " + sNumUses);
nNumUses = -1;
}
// Create the itemproperty and print it
iProp = ItemPropertyCastSpell(StringToInt(Get2DACache("shifter_abilitie", "IPSpell", i)), nNumUses);
_prc_inc_PrintItemProperty("=== ", oPC, iProp);
bPrinted = TRUE;
//TODO: DESTROY iProp?
// Increment property counter
nProps += 1;
}
// Increment loop counter
i += 1;
}
if(!bPrinted)
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(57481+0x01000000)); //"None"
}
void _prc_inc_shifting_PrintFeats(object oPC, object oTemplate, int nStartIndex, int nLimitIndex)
{
//Loop over shifter_feats.2da
string sFeat;
int i = nStartIndex;
while((i < nLimitIndex) && (sFeat = Get2DACache("shifter_feats", "Feat", i)) != "")
{
if (_prc_inc_GetHasFeat(oTemplate, StringToInt(sFeat)))
{
string sFeatName = GetStringByStrRef(StringToInt(Get2DACache("feat", "Feat", StringToInt(sFeat))));
_prc_inc_PrintShapeInfo(oPC, "=== " + sFeatName);
}
i += 1;
}
}
void _prc_inc_PrintNaturalAC(object oPC, object oTemplate)
{
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(57435+0x01000000) + " " + IntToString(_prc_inc_CreatureNaturalAC(oTemplate))); //Natural AC of form
}
//TODO: TLK Entries
void _prc_inc_PrintDebugItem(object oPC, string oItemType, object oItem)
{
if (GetIsObjectValid(oItem))
{
_prc_inc_PrintShapeInfo(oPC, "====================================");
_prc_inc_PrintShapeInfo(oPC, "====== " + oItemType);
_prc_inc_PrintShapeInfo(oPC, "====== NAME: " + GetName(oItem));
_prc_inc_PrintShapeInfo(oPC, "====== RESREF: " + GetResRef(oItem));
_prc_inc_PrintShapeInfo(oPC, "====== ITEM PROPERTIES ======");
_prc_inc_PrintAllItemProperties("=== ", oPC, oItem, TRUE);
_prc_inc_PrintShapeInfo(oPC, "====== EFFECTS ======");
_prc_inc_PrintAllEffects("=== ", oPC, oItem);
_prc_inc_PrintShapeInfo(oPC, "====== OTHER ======");
if (GetObjectType(oItem) == OBJECT_TYPE_CREATURE)
{
_prc_inc_PrintClassInfo("=== ", oPC, oItem, GetClassByPosition(1, oItem));
_prc_inc_PrintClassInfo("=== ", oPC, oItem, GetClassByPosition(2, oItem));
_prc_inc_PrintClassInfo("=== ", oPC, oItem, GetClassByPosition(3, oItem));
_prc_inc_PrintClassInfo("=== ", oPC, oItem, GetClassByPosition(4, oItem));
_prc_inc_PrintClassInfo("=== ", oPC, oItem, GetClassByPosition(5, oItem));
_prc_inc_PrintClassInfo("=== ", oPC, oItem, GetClassByPosition(6, oItem));
_prc_inc_PrintClassInfo("=== ", oPC, oItem, GetClassByPosition(7, oItem));
_prc_inc_PrintClassInfo("=== ", oPC, oItem, GetClassByPosition(8, oItem));
_prc_inc_PrintShapeInfo(oPC, "------");
_prc_inc_PrintShapeInfo(oPC, "====== Main hand weapon: " + (GetIsWeaponEffective(oItem, FALSE) ? "Effective" : "Ineffective"));
_prc_inc_PrintShapeInfo(oPC, "====== Off hand weapon: " + (GetIsWeaponEffective(oItem, TRUE) ? "Effective" : "Ineffective"));
_prc_inc_PrintShapeInfo(oPC, "====== Immortal: " + (GetImmortal(oItem) ? "Yes" : "No"));
_prc_inc_PrintShapeInfo(oPC, "------");
_prc_inc_PrintShapeInfo(oPC, "====== Level: " + IntToString(GetHitDice(oItem)));
_prc_inc_PrintShapeInfo(oPC, "====== CR: " + FloatToString(GetChallengeRating(oItem), 4, 1));
_prc_inc_PrintShapeInfo(oPC, "====== Caster Level: " + IntToString(GetCasterLevel(oItem)));
_prc_inc_PrintShapeInfo(oPC, "====== XP: " + IntToString(GetXP(oItem)));
_prc_inc_PrintShapeInfo(oPC, "====== Alignment: " + IntToString(GetLawChaosValue(oItem)) + " / " + IntToString(GetGoodEvilValue(oItem)));
//TODO:
// int GetAlignmentLawChaos(object oCreature);
// int GetAlignmentGoodEvil(object oCreature);
_prc_inc_PrintShapeInfo(oPC, "------");
_prc_inc_PrintShapeInfo(oPC, "====== BAB: " + IntToString(GetBaseAttackBonus(oItem)));
_prc_inc_PrintShapeInfo(oPC, "====== HP: " + IntToString(GetCurrentHitPoints(oItem)) + " / " + IntToString(GetMaxHitPoints(oItem)));
_prc_inc_PrintShapeInfo(oPC, "====== AC: " + IntToString(GetAC(oItem)));
_prc_inc_PrintShapeInfo(oPC, "====== SR: " + IntToString(GetSpellResistance(oItem)));
_prc_inc_PrintShapeInfo(oPC, "------");
//TODO: look up names in 2da/TLK?
_prc_inc_PrintShapeInfo(oPC, "====== STR: " + IntToString(GetAbilityScore(oItem, ABILITY_STRENGTH)) + " (" + IntToString(GetAbilityModifier(ABILITY_STRENGTH, oItem)) + ")");
_prc_inc_PrintShapeInfo(oPC, "====== DEX: " + IntToString(GetAbilityScore(oItem, ABILITY_DEXTERITY)) + " (" + IntToString(GetAbilityModifier(ABILITY_DEXTERITY, oItem)) + ")");
_prc_inc_PrintShapeInfo(oPC, "====== CON: " + IntToString(GetAbilityScore(oItem, ABILITY_CONSTITUTION)) + " (" + IntToString(GetAbilityModifier(ABILITY_CONSTITUTION, oItem)) + ")");
_prc_inc_PrintShapeInfo(oPC, "====== INT: " + IntToString(GetAbilityScore(oItem, ABILITY_INTELLIGENCE)) + " (" + IntToString(GetAbilityModifier(ABILITY_INTELLIGENCE, oItem)) + ")");
_prc_inc_PrintShapeInfo(oPC, "====== WIS: " + IntToString(GetAbilityScore(oItem, ABILITY_WISDOM)) + " (" + IntToString(GetAbilityModifier(ABILITY_WISDOM, oItem)) + ")");
_prc_inc_PrintShapeInfo(oPC, "====== CHA: " + IntToString(GetAbilityScore(oItem, ABILITY_CHARISMA)) + " (" + IntToString(GetAbilityModifier(ABILITY_CHARISMA, oItem)) + ")");
_prc_inc_PrintShapeInfo(oPC, "------");
//TODO: look up names in 2da/TLK?
_prc_inc_PrintShapeInfo(oPC, "====== Fortitude: " + IntToString(GetFortitudeSavingThrow(oItem)));
_prc_inc_PrintShapeInfo(oPC, "====== Will: " + IntToString(GetWillSavingThrow(oItem)));
_prc_inc_PrintShapeInfo(oPC, "====== Reflex: " + IntToString(GetReflexSavingThrow(oItem)));
_prc_inc_PrintShapeInfo(oPC, "------");
int i = 0;
string sSkillName;
while((sSkillName = Get2DACache("skills", "Name", i)) != "")
{
sSkillName = GetStringByStrRef(StringToInt(sSkillName));
_prc_inc_PrintShapeInfo(oPC, "====== " + sSkillName + ": " + IntToString(GetSkillRank(i, oItem)));
i += 1;
}
_prc_inc_PrintShapeInfo(oPC, "------");
_prc_inc_PrintShapeInfo(oPC, "====== Gender: " + IntToString(GetGender(oItem))); //TODO: look up values in 2da?
_prc_inc_PrintShapeInfo(oPC, "====== Size: " + IntToString(GetCreatureSize(oItem))); //TODO: look up values in 2da?
_prc_inc_PrintShapeInfo(oPC, "====== Race: " + IntToString(GetRacialType(oItem))); //TODO: look up values in 2da?
_prc_inc_PrintShapeInfo(oPC, "====== Speed: " + IntToString(GetMovementRate(oItem))); //TODO: look up values in 2da?
_prc_inc_PrintShapeInfo(oPC, "====== Dead: " + (GetIsDead(oItem) ? "Yes" : "No"));
_prc_inc_PrintShapeInfo(oPC, "====== Tag: " + GetTag(oItem));
_prc_inc_PrintShapeInfo(oPC, "====== Object Type: " + IntToString(GetObjectType(oItem))); //TODO: look up values in 2da?
//TODO?:
//int GetGold(object oTarget=OBJECT_SELF);
//location GetLocalLocation(object oObject, string sVarName);
// vector GetPositionFromLocation(location lLocation);
// object GetAreaFromLocation(location lLocation);
// float GetFacingFromLocation(location lLocation);
//int GetCommandable(object oTarget=OBJECT_SELF);
//int GetIsListening(object oObject);
//int GetReputation(object oSource, object oTarget);
//location GetLocation(object oObject);
//int GetIsPC(object oCreature);
// int GetIsEnemy(object oTarget, object oSource=OBJECT_SELF);
// int GetIsFriend(object oTarget, object oSource=OBJECT_SELF);
// int GetIsNeutral(object oTarget, object oSource=OBJECT_SELF);
// int GetStealthMode(object oCreature);
// int GetDetectMode(object oCreature);
// int GetDefensiveCastingMode(object oCreature);
// int GetAppearanceType(object oCreature);
// int GetWeight(object oTarget=OBJECT_SELF); //Gets the weight of an item, or the total carried weight of a creature in tenths of pounds (as per the baseitems.2da).
// int GetAILevel(object oTarget=OBJECT_SELF);
// int GetActionMode(object oCreature, int nMode);
// int GetArcaneSpellFailure(object oCreature);
// int GetLootable( object oCreature );
// int GetIsCreatureDisarmable(object oCreature);
// string GetDeity(object oCreature);
// string GetSubRace(object oTarget);
// int GetAge(object oCreature);
//int GetPlotFlag(object oTarget=OBJECT_SELF);
}
else
_prc_inc_PrintShapeInfo(oPC, "====== AC: " + IntToString(GetItemACValue(oItem)));
_prc_inc_PrintShapeInfo(oPC, "====================================");
}
}
//TODO: TLK Entries
void _prc_inc_ShapePrintDebug(object oPC, object oTarget, int bForceLogPrint)
{
int nSaveValue = GetLocalInt(oPC, "PRC_EnableLogPrint");
if (bForceLogPrint)
SetLocalInt(oPC, "PRC_EnableLogPrint", TRUE);
DelayCommand(0.0, _prc_inc_PrintDebugItem(oPC, "CREATURE", oTarget));
DelayCommand(0.0, _prc_inc_PrintDebugItem(oPC, "CREATURE SKIN", GetItemInSlot(INVENTORY_SLOT_CARMOUR, oTarget)));
DelayCommand(0.0, _prc_inc_PrintDebugItem(oPC, "RIGHT CREATURE WEAPON", GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oTarget)));
DelayCommand(0.0, _prc_inc_PrintDebugItem(oPC, "LEFT CREATURE WEAPON", GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oTarget)));
DelayCommand(0.0, _prc_inc_PrintDebugItem(oPC, "SPECIAL CREATURE WEAPON", GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oTarget)));
int nSlot;
for(nSlot = 0; nSlot < NUM_INVENTORY_SLOTS; nSlot++)
{
switch (nSlot)
{
case INVENTORY_SLOT_CARMOUR:
case INVENTORY_SLOT_CWEAPON_R:
case INVENTORY_SLOT_CWEAPON_L:
case INVENTORY_SLOT_CWEAPON_B:
break;
default:
DelayCommand(0.0, _prc_inc_PrintDebugItem(oPC, "INVENTORY ITEM " + IntToString(nSlot) + ": ", GetItemInSlot(nSlot, oTarget)));
}
}
if (bForceLogPrint)
DelayCommand(0.1, SetLocalInt(oPC, "PRC_EnableLogPrint", nSaveValue));
}
//TODO: Add nShifterType parameter so that only applicable information is printed?
void _prc_inc_PrintShape(object oPC, object oTemplate, int bForceLogPrint)
{
int nSaveValue = GetLocalInt(oPC, "PRC_EnableLogPrint");
if (bForceLogPrint)
SetLocalInt(oPC, "PRC_EnableLogPrint", TRUE);
_prc_inc_PrintShapeInfo(oPC, "=================================================");
//Basic information
_prc_inc_PrintShapeInfo(oPC, "=== " + GetName(oTemplate));
_prc_inc_PrintShapeInfo(oPC, "=== " + GetResRef(oTemplate));
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef((StringToInt(Get2DACache("racialtypes", "Name", MyPRCGetRacialType(oTemplate))))));
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(57420+0x01000000) + IntToString(_prc_inc_shifting_ShifterLevelRequirement(oTemplate))); //"Required Shifter Level: "
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(57421+0x01000000) + IntToString(_prc_inc_shifting_CharacterLevelRequirement(oTemplate))); //"Required Character Level: "
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(57436+0x01000000) + FloatToString(GetChallengeRating(oTemplate), 4, 1)); //"Challenge Rating: "
_prc_inc_PrintShapeInfo(oPC, "==========");
_prc_inc_PrintClassInfo("=== ", oPC, oTemplate, GetClassByPosition(1, oTemplate));
_prc_inc_PrintClassInfo("=== ", oPC, oTemplate, GetClassByPosition(2, oTemplate));
_prc_inc_PrintClassInfo("=== ", oPC, oTemplate, GetClassByPosition(3, oTemplate));
_prc_inc_PrintClassInfo("=== ", oPC, oTemplate, GetClassByPosition(4, oTemplate));
_prc_inc_PrintClassInfo("=== ", oPC, oTemplate, GetClassByPosition(5, oTemplate));
_prc_inc_PrintClassInfo("=== ", oPC, oTemplate, GetClassByPosition(6, oTemplate));
_prc_inc_PrintClassInfo("=== ", oPC, oTemplate, GetClassByPosition(7, oTemplate));
_prc_inc_PrintClassInfo("=== ", oPC, oTemplate, GetClassByPosition(8, oTemplate));
_prc_inc_PrintShapeInfo(oPC, "==========");
//Harmlessly invisible?
if(_prc_inc_shifting_GetIsCreatureHarmless(oTemplate))
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(57424+0x01000000)); //"Harmlessly Invisible"
//Able to cast spells without Natural Spell?
if(!_prc_inc_shifting_GetCanFormCast(oTemplate) && !GetHasFeat(FEAT_PRESTIGE_SHIFTER_NATURALSPELL, oTemplate))
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(57477+0x01000000)); //"Cannot cast spells"
else
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(57476+0x01000000)); //"Can cast spells"
//Natural AC
_prc_inc_PrintNaturalAC(oPC, oTemplate);
//STR, DEX, CON
struct _prc_inc_ability_info_struct rInfoStruct = _prc_inc_shifter_GetAbilityInfo(oTemplate, oPC);
//Extra information related to STR, DEX, CON
string sExtra, sBonusOrPenalty = GetStringByStrRef(57427+0x01000000);
sExtra = " (" + sBonusOrPenalty + (rInfoStruct.nDeltaSTR>=0?"+":"") + IntToString(rInfoStruct.nDeltaSTR) + ")";
_prc_inc_PrintShapeInfo(oPC, "=== " + _prc_inc_AbilityTypeString(0) + " " + IntToString(rInfoStruct.nTemplateSTR) + sExtra);
sExtra = " (" + sBonusOrPenalty + (rInfoStruct.nDeltaDEX>=0?"+":"") + IntToString(rInfoStruct.nDeltaDEX) + ")";
_prc_inc_PrintShapeInfo(oPC, "=== " + _prc_inc_AbilityTypeString(1) + " " + IntToString(rInfoStruct.nTemplateDEX) + sExtra);
sExtra = " (" + sBonusOrPenalty + (rInfoStruct.nDeltaCON>=0?"+":"") + IntToString(rInfoStruct.nDeltaCON) + ")";
_prc_inc_PrintShapeInfo(oPC, "=== " + _prc_inc_AbilityTypeString(2) + " " + IntToString(rInfoStruct.nTemplateCON) + sExtra);
_prc_inc_PrintShapeInfo(oPC, "------");
int i = 0;
string sSkillName;
string sSTRBasedSkills, sDEXBasedSkills, sCONBasedSkills;
while((sSkillName = Get2DACache("skills", "Name", i)) != "")
{
sSkillName = GetStringByStrRef(StringToInt(sSkillName));
string sSkillKeyAbility = Get2DACache("skills", "KeyAbility", i);
if (sSkillKeyAbility == "STR")
sSTRBasedSkills += sSkillName + ", ";
else if (sSkillKeyAbility == "DEX")
sDEXBasedSkills += sSkillName + ", ";
else if (sSkillKeyAbility == "CON")
sCONBasedSkills += sSkillName + ", ";
i += 1;
}
if (GetStringLength(sSTRBasedSkills))
sSTRBasedSkills = GetStringLeft(sSTRBasedSkills, GetStringLength(sSTRBasedSkills) - 2); //Remove the final ", "
if (GetStringLength(sDEXBasedSkills))
sDEXBasedSkills = GetStringLeft(sDEXBasedSkills, GetStringLength(sDEXBasedSkills) - 2); //Remove the final ", "
if (GetStringLength(sCONBasedSkills))
sCONBasedSkills = GetStringLeft(sCONBasedSkills, GetStringLength(sCONBasedSkills) - 2); //Remove the final ", "
int nSTRBonus = rInfoStruct.nExtraSTR / 2;
if (nSTRBonus > 0)
{
//TODO: cap AB bonus
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(60544+0x01000000) + " +" + IntToString(nSTRBonus)); //Attack increase from STR increase
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(60546+0x01000000) + " +" + IntToString(nSTRBonus)); //Damage increase from STR increase
_prc_inc_PrintShapeInfo(oPC, "=== " + ReplaceString(GetStringByStrRef(60528+0x01000000), "%(SKILLS)", sSTRBasedSkills) + " +" + IntToString(nSTRBonus)); //Skill bonus from STR increase
}
else if (nSTRBonus < 0)
{
//TODO: cap AB penalty--at what?
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(60545+0x01000000) + " " + IntToString(nSTRBonus)); //Attack decrease from STR decrease
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(60547+0x01000000) + " " + IntToString(nSTRBonus)); //Damage decrease from STR decrease
_prc_inc_PrintShapeInfo(oPC, "=== " + ReplaceString(GetStringByStrRef(60529+0x01000000), "%(SKILLS)", sSTRBasedSkills) + " " + IntToString(nSTRBonus)); //Skill penalty from STR decrease
}
int nDEXBonus = rInfoStruct.nExtraDEX / 2;
if (nDEXBonus > 0)
{
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(60548+0x01000000) + " +" + IntToString(nDEXBonus)); //AC increase from DEX increase
_prc_inc_PrintShapeInfo(oPC, "=== " + ReplaceString(GetStringByStrRef(60530+0x01000000), "%(SKILLS)", sDEXBasedSkills) + " +" + IntToString(nDEXBonus)); //Skill bonus from DEX increase
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(60531+0x01000000) + " +" + IntToString(nDEXBonus)); //Saving throw bonus from DEX increase
}
else if (nDEXBonus < 0)
{
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(60549+0x01000000) + " " + IntToString(nDEXBonus)); //AC decrease from DEX increase
_prc_inc_PrintShapeInfo(oPC, "=== " + ReplaceString(GetStringByStrRef(60532+0x01000000), "%(SKILLS)", sDEXBasedSkills) + " " + IntToString(nDEXBonus)); //Skill penalty from DEX decrease
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(60533+0x01000000) + " " + IntToString(nDEXBonus)); //Saving throw penalty from DEX decrease
}
int nCONBonus = rInfoStruct.nExtraCON / 2;
if (nCONBonus > 0)
{
_prc_inc_PrintShapeInfo(oPC, "=== " + ReplaceString(GetStringByStrRef(60534+0x01000000), "%(SKILLS)", sCONBasedSkills) + " +" + IntToString(nCONBonus)); //Skill bonus from CON increase
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(60535+0x01000000) + " +" + IntToString(nCONBonus)); //Saving throw bonus from CON increase
int tempHP = rInfoStruct.nExtraCON * GetHitDice(oPC);
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(57431+0x01000000) + " " + IntToString(tempHP)); //Temporary HP from CON increase
}
else if (nCONBonus < 0)
{
_prc_inc_PrintShapeInfo(oPC, "=== " + ReplaceString(GetStringByStrRef(60536+0x01000000), "%(SKILLS)", sCONBasedSkills) + " " + IntToString(nCONBonus)); //Skill penalty from CON decrease
_prc_inc_PrintShapeInfo(oPC, "=== " + GetStringByStrRef(60537+0x01000000) + " " + IntToString(nCONBonus)); //Saving throw penalty from CON decrease
}
_prc_inc_PrintShapeInfo(oPC, "==========");
//Hide and creature weapon properties
object oTemplateCWpR = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oTemplate);
object oTemplateCWpL = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oTemplate);
object oTemplateCWpB = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oTemplate);
object oTemplateHide = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oTemplate);
if(GetIsObjectValid(oTemplateCWpR))
{
string sPrefix = GetStringByStrRef(57432+0x01000000); //"Right Creature Weapon:"
_prc_inc_PrintShapeInfo(oPC, "=== " + sPrefix);
_prc_inc_PrintAllItemProperties("=== ", oPC, oTemplateCWpR);
}
if(GetIsObjectValid(oTemplateCWpL))
{
string sPrefix = GetStringByStrRef(57433+0x01000000); //"Left Creature Weapon:"
_prc_inc_PrintShapeInfo(oPC, "=== " + sPrefix);
_prc_inc_PrintAllItemProperties("=== ", oPC, oTemplateCWpL);
}
if(GetIsObjectValid(oTemplateCWpB))
{
string sPrefix = GetStringByStrRef(57434+0x01000000); //"Special Attack Creature Weapon:"
_prc_inc_PrintShapeInfo(oPC, "=== " + sPrefix);
_prc_inc_PrintAllItemProperties("=== ", oPC, oTemplateCWpB);
}
if(GetIsObjectValid(oTemplateHide))
_prc_inc_PrintAllItemProperties("=== ", oPC, oTemplateHide);
//Spell-like abilities
_prc_inc_shifting_PrintShifterActiveAbilities(oPC, oTemplate);
//Feats
i = 0;
string sFeat;
int CHUNK_SIZE = 25; //50 was too big, so use 25
while((sFeat = Get2DACache("shifter_feats", "Feat", i)) != "")
{
DelayCommand(0.0f, _prc_inc_shifting_PrintFeats(oPC, oTemplate, i, i+CHUNK_SIZE));
i += CHUNK_SIZE;
}
DelayCommand(0.0f, _prc_inc_PrintShapeInfo(oPC, "================================================="));
if (bForceLogPrint)
DelayCommand(0.1, SetLocalInt(oPC, "PRC_EnableLogPrint", nSaveValue));
if (GetLocalInt(oPC, "prc_shift_debug"))
DelayCommand(0.2f, _prc_inc_ShapePrintDebug(oPC, oTemplate, bForceLogPrint));
}