//:://///////////////////////////////////////////// //:: Summon Familiar //:: NW_S2_Familiar //:: Copyright (c) 2001 Bioware Corp. //::////////////////////////////////////////////// /* This spell summons an Arcane casters familiar */ //::////////////////////////////////////////////// //:: Created By: Preston Watamaniuk //:: Created On: Sept 27, 2001 //::////////////////////////////////////////////// #include "inc_dynconv" //#include "inc_dispel" #include "prc_inc_assoc" #include "prc_inc_template" const int PACKAGE_ELEMENTAL_STR = PACKAGE_ELEMENTAL; const int PACKAGE_ELEMENTAL_DEX = PACKAGE_FEY; void BondedSummoner(object oPC); void SummonPnPFamiliar(object oPC, int nType); void SummonPRCFamiliar(object oPC); void DreadNecro(object oPC); void MasterShadow(object oPC); void main() { object oPC = OBJECT_SELF; if(GetLevelByClass(CLASS_TYPE_MASTER_OF_SHADOW, oPC)) { //handles summoning of shadow familiar MasterShadow(oPC); } else if(GetLevelByClass(CLASS_TYPE_BONDED_SUMMONNER, oPC)) { //handles summoning of elemental familiar BondedSummoner(oPC); } else if(GetLevelByClass(CLASS_TYPE_DREAD_NECROMANCER, oPC) > 6) { //handles dread necromancer familiar DreadNecro(oPC); } else if(GetLevelByClass(CLASS_TYPE_CELEBRANT_SHARESS, oPC)) { //It's a PnP Cat familiar SummonPnPFamiliar(oPC, 6); } else if(GetPRCSwitch(PRC_PNP_FAMILIARS)) { //handles summoning of pnp familiar SummonPnPFamiliar(oPC, -1); } else if(GetPRCSwitch(PRC_FAMILIARS)//the switch is set || (!GetLevelByClass(CLASS_TYPE_WIZARD, oPC) && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC)))//or no bio-ware familiar { //handles summoning of familiars for PRC classes (witch, hexblade) SummonPRCFamiliar(oPC); } else //summon bio-ware familiar SummonFamiliar(); object oFam; int i; int bDiabol = GetLevelByClass(CLASS_TYPE_DIABOLIST, oPC) >= 2; int bPseudonat = GetHasFeat(FEAT_PSEUDONATURAL_FAMILIAR, oPC); for(i = 1; i <= 5; i++) { oFam = GetAssociateNPC(ASSOCIATE_TYPE_FAMILIAR, oPC, i); if(bDiabol && GetAppearanceType(oFam) != APPEARANCE_TYPE_IMP) DestroyAssociate(oFam); if(bPseudonat) { object oFamSkin = GetPCSkin(oFam); ApplyPseudonatural(oFam, oFamSkin); } } } void BondedSummoner(object oPC) { object oFam = GetAssociateNPC(ASSOCIATE_TYPE_FAMILIAR, oPC, NPC_BONDED_FAMILIAR); //remove previously summoned familiar if(GetIsObjectValid(oFam)) DestroyAssociate(oFam); string sResRef, sElem; int nPackage; if(GetHasFeat(FEAT_BONDED_AIR, oPC)) { sElem = "air"; nPackage = PACKAGE_ELEMENTAL_DEX; } else if(GetHasFeat(FEAT_BONDED_EARTH, oPC)) { sElem = "earth"; nPackage = PACKAGE_ELEMENTAL_STR; } else if(GetHasFeat(FEAT_BONDED_FIRE, oPC)) { sElem = "fire"; nPackage = PACKAGE_ELEMENTAL_DEX; } else if(GetHasFeat(FEAT_BONDED_WATER, oPC)) { sElem = "water"; nPackage = PACKAGE_ELEMENTAL_STR; } int nLevel = GetLevelByClass(CLASS_TYPE_BONDED_SUMMONNER, oPC); switch(nLevel) { case 1: case 2: sResRef = "x1_s_"+sElem+"small"; break;//this is the 4HD version in the SRD, which is medium case 3: case 4: sResRef = "prc_s_"+sElem+"large"; break; case 5: case 6: sResRef = "nw_s_"+sElem+"huge"; break; case 7: case 8: sResRef = "nw_s_"+sElem+"great"; break; case 9: case 10: sResRef = "nw_s_"+sElem+"elder"; break; } oFam = CreateLocalNPC(oPC, ASSOCIATE_TYPE_FAMILIAR, sResRef, PRCGetSpellTargetLocation(), NPC_BONDED_FAMILIAR); AddAssociate(oPC, oFam); //set its name string sName = GetFamiliarName(oPC); if(sName == "") sName = GetName(oPC)+ "'s Familiar"; SetName(oFam, sName); //apply bonus based on level int nArcaneLevel = GetPrCAdjustedCasterLevelByType(TYPE_ARCANE) + nLevel/2; object oSkin = GetPCSkin(oFam); //in all cases IPSafeAddItemProperty(oSkin, PRCItemPropertyBonusFeat(ITEM_PROPERTY_IMPROVED_EVASION)); //9+ levels if(nArcaneLevel >= 9) IPSafeAddItemProperty(oSkin, ItemPropertyBonusSpellResistance(GetSRByValue(nArcaneLevel+5))); //11+ levels if(nArcaneLevel >= 11) ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectMovementSpeedIncrease(30)), oFam); //add their ondeath special AddEventScript(oFam, EVENT_NPC_ONDEATH, "prc_bond_death"); /*int nAdjustLevel = nArcaneLevel - GetHitDice(oFam); int n; for(n = 1; nAdjustLevel >= n; n++) LevelUpHenchman(oFam, CLASS_TYPE_INVALID, TRUE, nPackage);*/ //set it so the spell-share detects it SetLocalObject(oPC, "Familiar", oFam); } void DreadNecro(object oPC) { object oFam = GetAssociateNPC(ASSOCIATE_TYPE_FAMILIAR, oPC, NPC_DN_FAMILIAR); //remove previously summoned familiar if(GetIsObjectValid(oFam)) DestroyAssociate(oFam); int bPnP = GetPRCSwitch(PRC_PNP_FAMILIARS); int nAlign = GetAlignmentLawChaos(oPC); string sResRef; if(bPnP) { sResRef = nAlign == ALIGNMENT_LAWFUL ? "prc_pnpfam_imp" : nAlign == ALIGNMENT_CHAOTIC ? "prc_pnpfam_qust" : "prc_pnpfam_varg"; } else { int nDNLevel = GetLevelByClass(CLASS_TYPE_DREAD_NECROMANCER, oPC); string sTemp = nDNLevel < 10 ? "0"+IntToString(nDNLevel) : IntToString(nDNLevel); sResRef = nAlign == ALIGNMENT_LAWFUL ? "NW_FM_IMP"+sTemp : nAlign == ALIGNMENT_CHAOTIC ? "NW_FM_QUAS"+sTemp : "X2_FM_EYE0"+sTemp; } oFam = CreateLocalNPC(oPC, ASSOCIATE_TYPE_FAMILIAR, sResRef, PRCGetSpellTargetLocation(), NPC_DN_FAMILIAR); //add the familiar as a henchman AddAssociate(oPC, oFam); //set its name string sName = GetFamiliarName(oPC); if(sName == "") sName = GetName(oPC)+ "'s Familiar"; SetName(oFam, sName); if(bPnP) ApplyPnPFamiliarProperties(oPC, oFam); } void SummonPnPFamiliar(object oPC, int nType) { IncrementRemainingFeatUses(oPC, FEAT_SUMMON_FAMILIAR); //check if already has a familiar object oFam = GetAssociateNPC(ASSOCIATE_TYPE_FAMILIAR, oPC, NPC_PNP_FAMILIAR); object oFamToken = GetItemPossessedBy(oPC, "prc_pnp_familiar"); int nFamiliarType; if (nType > 0) nFamiliarType = nType; else nFamiliarType = GetPersistantLocalInt(oPC, "PnPFamiliarType"); if(!nFamiliarType) { StartDynamicConversation("prc_pnp_fam_conv", oPC, DYNCONV_EXIT_ALLOWED_SHOW_CHOICE, TRUE, TRUE, oPC); return; } if(GetIsObjectValid(oFam)) { //reapply familiar bonuses PRCRemoveEffectsFromSpell(oFam, 318);//318 = summon familiar } else { if(GetIsObjectValid(oFamToken)) { DestroyObject(oFamToken, 0.1f); } //spawn the familiar string sResRef = Get2DACache("prc_familiar", "BASERESREF", nFamiliarType); oFam = CreateLocalNPC(oPC, ASSOCIATE_TYPE_FAMILIAR, sResRef, PRCGetSpellTargetLocation(), NPC_PNP_FAMILIAR); //set its name string sName = GetFamiliarName(oPC); if(sName == "") sName = GetName(oPC)+ "'s Familiar"; SetName(oFam, sName); //add the familiar as a henchman AddAssociate(oPC, oFam); } //this is the masters bonus effect eBonus = GetMasterBonus(nFamiliarType); eBonus = SupernaturalEffect(eBonus); if(!GetHasFeatEffect(FEAT_SUMMON_FAMILIAR, oPC)) { ApplyEffectToObject(DURATION_TYPE_PERMANENT, eBonus, oPC); CheckIsValidFamiliar(oPC, eBonus); } ApplyPnPFamiliarProperties(oPC, oFam); if (GetHasFeat(FEAT_SHADOW_FAMILIAR, oPC)) ApplyTemplateToObject(TEMPLATE_DARK, oFam); } void SummonPRCFamiliar(object oPC) { object oFam = GetAssociateNPC(ASSOCIATE_TYPE_FAMILIAR, oPC, NPC_HENCHMAN_COMPANION); //remove previously summoned familiar if(GetIsObjectValid(oFam)) DestroyAssociate(oFam); int nFamiliarType = GetPersistantLocalInt(oPC, "FamiliarType"); if(!nFamiliarType) { StartDynamicConversation("prc_pnp_fam_conv", oPC, DYNCONV_EXIT_ALLOWED_SHOW_CHOICE, TRUE, TRUE, oPC); IncrementRemainingFeatUses(oPC, FEAT_SUMMON_FAMILIAR); return; } else nFamiliarType--; int nFamLevel = GetLevelByClass(CLASS_TYPE_WIZARD); nFamLevel = PRCMax(nFamLevel, GetLevelByClass(CLASS_TYPE_SORCERER)); nFamLevel = PRCMax(nFamLevel, GetLevelByClass(CLASS_TYPE_WITCH)); nFamLevel = PRCMax(nFamLevel, GetLevelByClass(CLASS_TYPE_HEXBLADE)); nFamLevel += GetLevelByClass(CLASS_TYPE_ALIENIST); if (GetHasFeat(FEAT_SHADOW_FAMILIAR, oPC)) nFamLevel = GetLevelByTypeArcane(oPC) + GetShadowcasterLevel(oPC); // For the purpose of determining familiar abilities that depend on your arcane caster level, your levels in all classes that allow you to cast mysteries or arcane spells stack string sTemp = Get2DACache("hen_familiar", "BASERESREF", nFamiliarType); string sResRef = nFamLevel < 10 ? sTemp+"0"+IntToString(nFamLevel) : sTemp+IntToString(nFamLevel); //spawn the familiar oFam = CreateLocalNPC(oPC, ASSOCIATE_TYPE_FAMILIAR, sResRef, PRCGetSpellTargetLocation(), NPC_HENCHMAN_COMPANION); AddAssociate(oPC, oFam); if (GetHasFeat(FEAT_SHADOW_FAMILIAR, oPC)) ApplyTemplateToObject(TEMPLATE_DARK, oFam); //set its name string sName = GetFamiliarName(oPC); if(sName == "") sName = GetName(oPC)+ "'s Familiar"; SetName(oFam, sName); } void MasterShadow(object oPC) { object oFam = GetAssociateNPC(ASSOCIATE_TYPE_FAMILIAR, oPC, NPC_MS_ELEMENTAL); //remove previously summoned familiar if(GetIsObjectValid(oFam)) DestroyAssociate(oFam); int nLevel = GetLevelByClass(CLASS_TYPE_MASTER_OF_SHADOW, oPC); string sShadow = "shd_shdelem_med"; if (nLevel >= 10) sShadow = "shd_shdelem_med4"; else if (nLevel >= 7) sShadow = "shd_shdelem_med3"; else if (nLevel >= 4) sShadow = "shd_shdelem_med2"; oFam = CreateLocalNPC(oPC, ASSOCIATE_TYPE_FAMILIAR, sShadow, PRCGetSpellTargetLocation(), NPC_MS_ELEMENTAL); AddAssociate(oPC, oFam); //set its name string sName = GetFamiliarName(oPC); if(sName == "") sName = GetName(oPC)+ "'s Shadow Elemental"; SetName(oFam, sName); itemproperty ipIP; object oSkin = GetPCSkin(oFam); if (nLevel >= 10) ipIP =ItemPropertyDamageImmunity(IP_CONST_DAMAGETYPE_COLD,IP_CONST_DAMAGEIMMUNITY_100_PERCENT); else if (nLevel >= 6) ipIP =ItemPropertyDamageResistance(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGERESIST_20); else if (nLevel >= 4) ipIP =ItemPropertyDamageResistance(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGERESIST_10); else if (nLevel >= 2) ipIP =ItemPropertyDamageResistance(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGERESIST_5); IPSafeAddItemProperty(oSkin, ipIP, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE); if (nLevel >= 3) // Grow to size large SetCreatureAppearanceType(oFam, APPEARANCE_TYPE_SHADOW_FIEND); }