//:: 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)); }