/* Evolved Undead By: Jaysyn Created: 2024-11-14 17:50:32 An evolved undead is an undead whose body is flushed with more negative energy than normal due to an exceptionally long lifetime. Any undead may gain this template, and in doing so, it retains all its previous abilities, but becomes more powerful than before. */ #include "nw_inc_gff" #include "npc_template_inc" #include "prc_inc_spells" #include "prc_inc_util" //:: Adds Evolved SLA's to jCreature. //:: json json_AddEvolvedPowers(json jCreature, int nBaseHD, int nCasterLevel, int iEvolution) { int nRandom = d12(1); // Get the existing SpecAbilityList (if it exists) json jSpecAbilityList = GffGetList(jCreature, "SpecAbilityList"); // Create the SpecAbilityList if it doesn't exist if (jSpecAbilityList == JsonNull()) { jSpecAbilityList = JsonArray(); } /* 1 circle of death 6 2 cloudkill 5 3 cone of cold 4 4 confusion 3 5 contagion 27 - 3rd 6 creeping doom 364 - 7th 7 greater dispel magic 67 - 5th 8 greater invisibility 88 - 4th 9 haste 78 - 3rd 10 hold monster 82 - 4th 11 see invisibility 157 - 2nd 12 unholy blight 566 - 5th */ switch(nRandom) { case 1: if (nBaseHD >= 6) { int i; for (i = 0; i < 1; i++) { json jSpecAbility = JsonObject(); jSpecAbility = GffAddWord(jSpecAbility, "Spell", 18); jSpecAbility = GffAddByte(jSpecAbility, "SpellCasterLevel", PRCMax(nCasterLevel, nBaseHD)); jSpecAbility = GffAddByte(jSpecAbility, "SpellFlags", 1); // Manually add to the array jSpecAbilityList = JsonArrayInsert(jSpecAbilityList, jSpecAbility); } } else { return json_AddEvolvedPowers(jCreature, nBaseHD, nCasterLevel, iEvolution); } break; case 2: if (nBaseHD >= 5) { int i; for (i = 0; i < 1; i++) { json jSpecAbility = JsonObject(); jSpecAbility = GffAddWord(jSpecAbility, "Spell", 23); jSpecAbility = GffAddByte(jSpecAbility, "SpellCasterLevel", PRCMax(nCasterLevel, nBaseHD)); jSpecAbility = GffAddByte(jSpecAbility, "SpellFlags", 1); // Manually add to the array jSpecAbilityList = JsonArrayInsert(jSpecAbilityList, jSpecAbility); } } else { return json_AddEvolvedPowers(jCreature, nBaseHD, nCasterLevel, iEvolution); } break; case 3: if (nBaseHD >= 4) { int i; for (i = 0; i < 1; i++) { json jSpecAbility = JsonObject(); jSpecAbility = GffAddWord(jSpecAbility, "Spell", 25); jSpecAbility = GffAddByte(jSpecAbility, "SpellCasterLevel", PRCMax(nCasterLevel, nBaseHD)); jSpecAbility = GffAddByte(jSpecAbility, "SpellFlags", 1); // Manually add to the array jSpecAbilityList = JsonArrayInsert(jSpecAbilityList, jSpecAbility); } } else { return json_AddEvolvedPowers(jCreature, nBaseHD, nCasterLevel, iEvolution); } break; case 4: if (nBaseHD >= 3) { int i; for (i = 0; i < 1; i++) { json jSpecAbility = JsonObject(); jSpecAbility = GffAddWord(jSpecAbility, "Spell", 26); jSpecAbility = GffAddByte(jSpecAbility, "SpellCasterLevel", PRCMax(nCasterLevel, nBaseHD)); jSpecAbility = GffAddByte(jSpecAbility, "SpellFlags", 1); // Manually add to the array jSpecAbilityList = JsonArrayInsert(jSpecAbilityList, jSpecAbility); } } else { return json_AddEvolvedPowers(jCreature, nBaseHD, nCasterLevel, iEvolution); } break; case 5: if (nBaseHD >= 3) { int i; for (i = 0; i < 1; i++) { json jSpecAbility = JsonObject(); jSpecAbility = GffAddWord(jSpecAbility, "Spell", 27); jSpecAbility = GffAddByte(jSpecAbility, "SpellCasterLevel", PRCMax(nCasterLevel, nBaseHD)); jSpecAbility = GffAddByte(jSpecAbility, "SpellFlags", 1); // Manually add to the array jSpecAbilityList = JsonArrayInsert(jSpecAbilityList, jSpecAbility); } } else { return json_AddEvolvedPowers(jCreature, nBaseHD, nCasterLevel, iEvolution); } break; case 6: if (nBaseHD >= 7) { int i; for (i = 0; i < 1; i++) { json jSpecAbility = JsonObject(); jSpecAbility = GffAddWord(jSpecAbility, "Spell", 364); jSpecAbility = GffAddByte(jSpecAbility, "SpellCasterLevel", PRCMax(nCasterLevel, nBaseHD)); jSpecAbility = GffAddByte(jSpecAbility, "SpellFlags", 1); // Manually add to the array jSpecAbilityList = JsonArrayInsert(jSpecAbilityList, jSpecAbility); } } else { return json_AddEvolvedPowers(jCreature, nBaseHD, nCasterLevel, iEvolution); } break; case 7: if (nBaseHD >= 5) { int i; for (i = 0; i < 1; i++) { json jSpecAbility = JsonObject(); jSpecAbility = GffAddWord(jSpecAbility, "Spell", 67); jSpecAbility = GffAddByte(jSpecAbility, "SpellCasterLevel", PRCMax(nCasterLevel, nBaseHD)); jSpecAbility = GffAddByte(jSpecAbility, "SpellFlags", 1); // Manually add to the array jSpecAbilityList = JsonArrayInsert(jSpecAbilityList, jSpecAbility); } } else { return json_AddEvolvedPowers(jCreature, nBaseHD, nCasterLevel, iEvolution); } break; case 8: if (nBaseHD >= 4) { int i; for (i = 0; i < 1; i++) { json jSpecAbility = JsonObject(); jSpecAbility = GffAddWord(jSpecAbility, "Spell", 88); jSpecAbility = GffAddByte(jSpecAbility, "SpellCasterLevel", PRCMax(nCasterLevel, nBaseHD)); jSpecAbility = GffAddByte(jSpecAbility, "SpellFlags", 1); // Manually add to the array jSpecAbilityList = JsonArrayInsert(jSpecAbilityList, jSpecAbility); } } else { return json_AddEvolvedPowers(jCreature, nBaseHD, nCasterLevel, iEvolution); } break; case 9: if (nBaseHD >= 3) { int i; for (i = 0; i < 1; i++) { json jSpecAbility = JsonObject(); jSpecAbility = GffAddWord(jSpecAbility, "Spell", 78); jSpecAbility = GffAddByte(jSpecAbility, "SpellCasterLevel", PRCMax(nCasterLevel, nBaseHD)); jSpecAbility = GffAddByte(jSpecAbility, "SpellFlags", 1); // Manually add to the array jSpecAbilityList = JsonArrayInsert(jSpecAbilityList, jSpecAbility); } } else { return json_AddEvolvedPowers(jCreature, nBaseHD, nCasterLevel, iEvolution); } break; case 10: if (nBaseHD >= 4) { int i; for (i = 0; i < 1; i++) { json jSpecAbility = JsonObject(); jSpecAbility = GffAddWord(jSpecAbility, "Spell", 82); jSpecAbility = GffAddByte(jSpecAbility, "SpellCasterLevel", PRCMax(nCasterLevel, nBaseHD)); jSpecAbility = GffAddByte(jSpecAbility, "SpellFlags", 1); // Manually add to the array jSpecAbilityList = JsonArrayInsert(jSpecAbilityList, jSpecAbility); } } else { return json_AddEvolvedPowers(jCreature, nBaseHD, nCasterLevel, iEvolution); } break; case 11: if (nBaseHD >= 2) { int i; for (i = 0; i < 1; i++) { json jSpecAbility = JsonObject(); jSpecAbility = GffAddWord(jSpecAbility, "Spell", 157); jSpecAbility = GffAddByte(jSpecAbility, "SpellCasterLevel", PRCMax(nCasterLevel, nBaseHD)); jSpecAbility = GffAddByte(jSpecAbility, "SpellFlags", 1); // Manually add to the array jSpecAbilityList = JsonArrayInsert(jSpecAbilityList, jSpecAbility); } } else { return json_AddEvolvedPowers(jCreature, nBaseHD, nCasterLevel, iEvolution); } break; case 12: if (nBaseHD >= 5) { int i; for (i = 0; i < 1; i++) { json jSpecAbility = JsonObject(); jSpecAbility = GffAddWord(jSpecAbility, "Spell", 566); jSpecAbility = GffAddByte(jSpecAbility, "SpellCasterLevel", PRCMax(nCasterLevel, nBaseHD)); jSpecAbility = GffAddByte(jSpecAbility, "SpellFlags", 1); // Manually add to the array jSpecAbilityList = JsonArrayInsert(jSpecAbilityList, jSpecAbility); } } else { return json_AddEvolvedPowers(jCreature, nBaseHD, nCasterLevel, iEvolution); } break; default: // Fallback to Doom for creatures with 1HD or less. int i; for (i = 0; i < 1; i++) { json jSpecAbility = JsonObject(); jSpecAbility = GffAddWord(jSpecAbility, "Spell", 46); // Doom spell jSpecAbility = GffAddByte(jSpecAbility, "SpellCasterLevel", PRCMax(nCasterLevel, nBaseHD)); jSpecAbility = GffAddByte(jSpecAbility, "SpellFlags", 1); jSpecAbilityList = JsonArrayInsert(jSpecAbilityList, jSpecAbility); } break; } return jCreature = GffAddList(jCreature, "SpecAbilityList", jSpecAbilityList); } //:: Apply Evolved effects to a non-PC creature void ApplyEvolvedEffects(object oCreature, int nBaseHD, int nCasterLevel, int iEvolution) { //:: Declare major variables int bIncorporeal = GetIsIncorporeal(oCreature); effect eVolved; //:: Boost caster & SLA level SetLocalInt(oCreature, PRC_CASTERLEVEL_ADJUSTMENT, PRCMax(nCasterLevel, nBaseHD)); //:: AC Bonuses: +1 natural or +1 deflection if Incorporal if(bIncorporeal) { eVolved = EffectACIncrease(1+iEvolution, AC_DEFLECTION_BONUS); } else { eVolved = EffectACIncrease(1+iEvolution, AC_NATURAL_BONUS); } //:: Fast Healing 3 eVolved = EffectLinkEffects(eVolved, EffectRegenerate(3, 6.0f)); //:: Make *really* permanent eVolved = UnyieldingEffect(eVolved); //:: Apply everything ApplyEffectToObject(DURATION_TYPE_PERMANENT, eVolved, oCreature); } void main() { //:: Declare major variables object oBaseCreature = OBJECT_SELF; object oNewCreature; int bIncorporeal = GetIsIncorporeal(oBaseCreature); int iBaseRace = MyPRCGetRacialType(oBaseCreature); int nCasterLevel = PRCGetCasterLevel(oBaseCreature); int iEvolution = GetLocalInt(oBaseCreature, "UNDEAD_EVOLUTION"); //:: Creatures & NPCs only if ((GetObjectType(oBaseCreature) != OBJECT_TYPE_CREATURE) || (GetIsPC(oBaseCreature) == TRUE)) { if(DEBUG) DoDebug("Not a creature"); return; } //:: Undead only if(iBaseRace != RACIAL_TYPE_UNDEAD) { //SendMessageToPC(GetFirstPC(), "make_evolved: Invalid racial type for template."); if(DEBUG) DoDebug("make_evolved: Invalid racial type for template."); return; } int nBaseHD = GetHitDice(oBaseCreature); int nBaseCR = FloatToInt(GetChallengeRating(oBaseCreature)); json jBaseCreature = ObjectToJson(oBaseCreature, TRUE); json jNewCreature; json jFinalCreature; //:: Add Spell-like abilities jNewCreature = json_AddEvolvedPowers(jBaseCreature, nBaseHD, nCasterLevel, iEvolution); //:: Update stats if(bIncorporeal) { //:: Incorporeal = CHA only jNewCreature = json_UpdateStats(jNewCreature, oBaseCreature, 0, 0, 0, 0, 0, 2); } else { jNewCreature = json_UpdateStats(jNewCreature, oBaseCreature, 2, 0, 0, 0, 0, 2); } //:: Update CR jFinalCreature = json_UpdateCR(jNewCreature, nBaseCR, 1); //:: Update the creature oNewCreature = JsonToObject(jFinalCreature, GetLocation(oBaseCreature)); DestroyObject(oBaseCreature, 0.0f); //:: Apply effects ApplyEvolvedEffects(oNewCreature, nBaseHD, nCasterLevel, iEvolution); PRCForceRest(oNewCreature); //:: Update creature's name on first advancement string sBaseName = GetName(oNewCreature); if(iEvolution < 1) { SetName(oNewCreature, "Evolved "+ sBaseName); } if(iEvolution < 4) { SetName(oNewCreature, "Greater "+ sBaseName); } //:: Update race field SetSubRace(oNewCreature, "Undead (Augmented)"); SetAge(oNewCreature, GetAge(oNewCreature) + d100(1)); //:: Set variables SetLocalInt(oNewCreature, "UNDEAD_EVOLUTION", iEvolution+1); SetLocalInt(oNewCreature, "TEMPLATE_EVOLVED", 1); }