Setup onSpawn Evolved Undead template
Setup onSpawn Evolved Undead template. Started baseitem work for new iprop forge system. Full compile. Updated release archive.
This commit is contained in:
@@ -43,7 +43,8 @@ const int EVENT_USER_DEFINED_POSTSPAWN = 1511;
|
||||
|
||||
#include "ms_name_inc"
|
||||
#include "x2_inc_switches"
|
||||
|
||||
#include "prc_inc_racial"
|
||||
#include "sd_lootsystem"
|
||||
|
||||
void Embiggen(object oNPC, float fIncrease);
|
||||
|
||||
@@ -52,6 +53,44 @@ void Embiggen(object oNPC, float fIncrease)
|
||||
SetObjectVisualTransform(OBJECT_SELF, OBJECT_VISUAL_TRANSFORM_SCALE, fIncrease);
|
||||
}
|
||||
|
||||
void EvolvedUndeadCheck(object oUndead)
|
||||
{
|
||||
// Check if the creature is undead and intelligent
|
||||
if (MyPRCGetRacialType(oUndead) != RACIAL_TYPE_UNDEAD || !GetAbilityModifier(ABILITY_INTELLIGENCE, oUndead) > -1)
|
||||
{
|
||||
return; // Exit if not an intelligent undead
|
||||
}
|
||||
|
||||
// Get the undead's area and its age
|
||||
object oArea = GetArea(oUndead);
|
||||
int iUndeadAge = GetAge(oUndead);
|
||||
|
||||
// Base evolution chance: 1% for every 100 years
|
||||
int iBaseChance = iUndeadAge / 100;
|
||||
|
||||
// Add chance modifiers: ancient energy and previous evolutions
|
||||
int iAncientBoost = GetLocalInt(oArea, "EVO_UNDEAD_BOOST"); // Area-specific boost
|
||||
int iEvolutionCount = GetLocalInt(oUndead, "UNDEAD_EVOLUTION"); // Previous evolutions
|
||||
int iChance = iBaseChance + iAncientBoost + iEvolutionCount;
|
||||
|
||||
// Roll the dice (1-100)
|
||||
int iRoll = Random(100) + 1;
|
||||
|
||||
// Debug message to monitor rolls and chances
|
||||
if(DEBUG)
|
||||
{
|
||||
DoDebug("Evolution Check: Roll = " + IntToString(iRoll) + ", Chance = " + IntToString(iChance));
|
||||
}
|
||||
|
||||
// Check if the undead evolves
|
||||
if (iRoll <= iChance)
|
||||
{
|
||||
// Apply evolution template
|
||||
ExecuteScript("make_evolved", oUndead); // Apply template script
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
@@ -66,6 +105,8 @@ void main()
|
||||
|
||||
//:: Declare major variables
|
||||
object oNPC;
|
||||
|
||||
int iRace = MyPRCGetRacialType(OBJECT_SELF);
|
||||
|
||||
string sTag;
|
||||
string sResRef = GetResRef(OBJECT_SELF);
|
||||
@@ -577,9 +618,22 @@ void main()
|
||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, OBJECT_SELF);
|
||||
}
|
||||
|
||||
//:: Setup Evolved Undead
|
||||
if(iRace == RACIAL_TYPE_UNDEAD)
|
||||
{
|
||||
SetAge(OBJECT_SELF, d20(6));
|
||||
|
||||
EvolvedUndeadCheck(OBJECT_SELF);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//:: Set or Randomize name
|
||||
ms_Nomenclature(OBJECT_SELF);
|
||||
|
||||
//:: Set threatlevel name text
|
||||
SetThreatLevel(OBJECT_SELF);
|
||||
|
||||
//:: Execute OnSpawn script.
|
||||
int nSpider = GetStringLeft(GetTag(OBJECT_SELF), 12) == "MONST_SPIDER" ? TRUE : FALSE;
|
||||
if(nSpider)
|
||||
|
414
_module/nss/make_evolved.nss
Normal file
414
_module/nss/make_evolved.nss
Normal file
@@ -0,0 +1,414 @@
|
||||
/* 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", max(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", max(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", max(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", max(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", max(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", max(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", max(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", max(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", max(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", max(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", max(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", max(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", max(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, max(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);
|
||||
}
|
174
_module/nss/npc_template_inc.nss
Normal file
174
_module/nss/npc_template_inc.nss
Normal file
@@ -0,0 +1,174 @@
|
||||
/* npc_template_inc
|
||||
|
||||
Common functions for Creature Templates
|
||||
|
||||
By: Jaysyn
|
||||
Created: 2024-11-14 08:27:30
|
||||
|
||||
*/
|
||||
#include "prc_inc_fork"
|
||||
#include "nw_inc_gff"
|
||||
#include "prc_inc_natweap"
|
||||
#include "prc_inc_util"
|
||||
|
||||
void ReallyEquipItemInSlot(object oNPC, object oItem, int nSlot);
|
||||
|
||||
void ReallyEquipItemInSlot(object oNPC, object oItem, int nSlot)
|
||||
{
|
||||
if (GetItemInSlot(nSlot) != oItem)
|
||||
{
|
||||
//ClearAllActions();
|
||||
AssignCommand(oNPC, ActionEquipItem(oItem, nSlot));
|
||||
DelayCommand(0.5, ReallyEquipItemInSlot(oNPC, oItem, nSlot));
|
||||
}
|
||||
}
|
||||
|
||||
//:: Immunity to all gaze attacks
|
||||
effect EffectGazeImmune()
|
||||
{
|
||||
effect eBlank;
|
||||
|
||||
effect eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_CHARM);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_CHARM);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_CONFUSION);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DAZE);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DEATH);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DESTROY_CHAOS);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DESTROY_EVIL);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DESTROY_GOOD);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DESTROY_LAW);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DOMINATE);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DOOM);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_FEAR);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_PARALYSIS);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_STUNNED);
|
||||
eReturn = TagEffect(eReturn, "PRCGazeImmune");
|
||||
|
||||
return eReturn;
|
||||
}
|
||||
|
||||
// Get the size of a JSON array
|
||||
int GetJsonArraySize(json jArray)
|
||||
{
|
||||
int iSize = 0;
|
||||
while (JsonArrayGet(jArray, iSize) != JsonNull())
|
||||
{
|
||||
iSize++;
|
||||
}
|
||||
return iSize;
|
||||
}
|
||||
|
||||
int CheckForWeapon(object oCreature)
|
||||
{
|
||||
if (GetIsWeapon(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature)) == 1 || GetIsWeapon(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature)) == 1)
|
||||
{
|
||||
// oCreature has a weapon in at least one hand
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// oCreature doesn't have a weapon in either hand
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//:: Directly modifies jCreature's Challenge Rating.
|
||||
//:: This is useful for most XP calculations.
|
||||
//::
|
||||
json json_UpdateCR(json jCreature, int nBaseCR, int nCRMod)
|
||||
{
|
||||
int nNewCR;
|
||||
|
||||
//:: Add CRMod to current CR
|
||||
nNewCR = nBaseCR + nCRMod;
|
||||
|
||||
//:: Modify Challenge Rating
|
||||
jCreature = GffReplaceFloat(jCreature, "ChallengeRating", IntToFloat(nNewCR));
|
||||
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
|
||||
//:: Directly modifies oCreature's ability scores.
|
||||
//::
|
||||
json json_UpdateStats(json jCreature, object oBaseCreature, int iModStr = 0, int iModDex = 0, int iModCon = 0, int iModInt = 0, int iModWis = 0, int iModCha = 0)
|
||||
{
|
||||
//:: Retrieve and modify ability scores
|
||||
int iCurrentStr = GetAbilityScore(oBaseCreature, ABILITY_STRENGTH);
|
||||
int iCurrentDex = GetAbilityScore(oBaseCreature, ABILITY_DEXTERITY);
|
||||
int iCurrentCon = GetAbilityScore(oBaseCreature, ABILITY_CONSTITUTION);
|
||||
int iCurrentInt = GetAbilityScore(oBaseCreature, ABILITY_INTELLIGENCE);
|
||||
int iCurrentWis = GetAbilityScore(oBaseCreature, ABILITY_WISDOM);
|
||||
int iCurrentCha = GetAbilityScore(oBaseCreature, ABILITY_CHARISMA);
|
||||
|
||||
jCreature = GffReplaceByte(jCreature, "Str", iCurrentStr + iModStr);
|
||||
jCreature = GffReplaceByte(jCreature, "Dex", iCurrentDex + iModDex);
|
||||
jCreature = GffReplaceByte(jCreature, "Con", iCurrentCon + iModCon);
|
||||
jCreature = GffReplaceByte(jCreature, "Int", iCurrentInt + iModInt);
|
||||
jCreature = GffReplaceByte(jCreature, "Wis", iCurrentWis + iModWis);
|
||||
jCreature = GffReplaceByte(jCreature, "Cha", iCurrentCha + iModCha);
|
||||
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
//:: Directly modifies oCreature's Base Natural AC if iNewAC is higher.
|
||||
//::
|
||||
json json_UpdateBaseAC(json jCreature, int iNewAC)
|
||||
{
|
||||
//json jBaseAC = GffGetByte(jCreature, "Creature/value/NaturalAC/value");
|
||||
json jBaseAC = GffGetByte(jCreature, "NaturalAC");
|
||||
|
||||
if (jBaseAC == JsonNull())
|
||||
{
|
||||
return JsonNull();
|
||||
}
|
||||
else if (JsonGetInt(jBaseAC) > iNewAC)
|
||||
{
|
||||
return jCreature;
|
||||
}
|
||||
else
|
||||
{
|
||||
jCreature = GffReplaceByte(jCreature, "NaturalAC", iNewAC);
|
||||
|
||||
return jCreature;
|
||||
}
|
||||
}
|
||||
|
||||
//:: Function to calculate the maximum possible hitpoints for oCreature
|
||||
int GetMaxPossibleHP(object oCreature)
|
||||
{
|
||||
int nMaxHP = 0; // Stores the total maximum hitpoints
|
||||
int i = 1; // Initialize position for class index
|
||||
int nConb = GetAbilityModifier(ABILITY_CONSTITUTION, oCreature);
|
||||
|
||||
// Loop through each class position the creature may have, checking each class in turn
|
||||
while (TRUE)
|
||||
{
|
||||
// Get the class ID at position i
|
||||
int nClassID = GetClassByPosition(i, oCreature);
|
||||
|
||||
// If class is invalid (no more classes to check), break out of loop
|
||||
if (nClassID == CLASS_TYPE_INVALID)
|
||||
break;
|
||||
|
||||
// Get the number of levels in this class
|
||||
int nClassLevels = GetLevelByClass(nClassID, oCreature);
|
||||
|
||||
// Get the row index of the class in classes.2da by using class ID as the row index
|
||||
int nHitDie = StringToInt(Get2DAString("classes", "HitDie", nClassID));
|
||||
|
||||
// Add maximum HP for this class (Hit Die * number of levels in this class)
|
||||
nMaxHP += nClassLevels * nHitDie;
|
||||
|
||||
// Move to the next class position
|
||||
i++;
|
||||
}
|
||||
|
||||
nMaxHP += nConb * GetHitDice(oCreature);
|
||||
|
||||
return nMaxHP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//:: void main(){}
|
@@ -20,16 +20,20 @@ void SendMessageToAllPC(string sMessage);
|
||||
|
||||
void SetTlkOverrideForMaximumLevel(object oPC)
|
||||
{
|
||||
int nLevel = GetHitDice(oPC);
|
||||
|
||||
if (nLevel < 40)
|
||||
{
|
||||
NWNX_Player_SetTlkOverride(oPC, 315, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
NWNX_Player_SetTlkOverride(oPC, 315, "Next Level: " + IntToString((nLevel + 1) * nLevel * 500) + "\n");
|
||||
}
|
||||
int nLevel = GetHitDice(oPC);
|
||||
|
||||
if (nLevel >= 60)
|
||||
{
|
||||
NWNX_Player_SetTlkOverride(oPC, 315, "Maximum Level");
|
||||
}
|
||||
else if (nLevel > 39)
|
||||
{
|
||||
NWNX_Player_SetTlkOverride(oPC, 315, "Next Level: " + IntToString((nLevel + 1) * nLevel * 500) + "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
NWNX_Player_SetTlkOverride(oPC, 315, "");
|
||||
}
|
||||
}
|
||||
|
||||
void SendMessageToAllPC(string sMessage)
|
||||
|
@@ -27,6 +27,44 @@ void ReallyEquipItemInSlot(object oNPC, object oItem, int nSlot)
|
||||
}
|
||||
}
|
||||
|
||||
void EvolvedUndeadCheck(object oUndead)
|
||||
{
|
||||
// Check if the creature is undead and intelligent
|
||||
if (MyPRCGetRacialType(oUndead) != RACIAL_TYPE_UNDEAD || !GetAbilityModifier(ABILITY_INTELLIGENCE, oUndead) > -1)
|
||||
{
|
||||
return; // Exit if not an intelligent undead
|
||||
}
|
||||
|
||||
// Get the undead's area and its age
|
||||
object oArea = GetArea(oUndead);
|
||||
int iUndeadAge = GetAge(oUndead);
|
||||
|
||||
// Base evolution chance: 1% for every 100 years
|
||||
int iBaseChance = iUndeadAge / 100;
|
||||
|
||||
// Add chance modifiers: ancient energy and previous evolutions
|
||||
int iAncientBoost = GetLocalInt(oArea, "EVO_UNDEAD_BOOST"); // Area-specific boost
|
||||
int iEvolutionCount = GetLocalInt(oUndead, "UNDEAD_EVOLUTION"); // Previous evolutions
|
||||
int iChance = iBaseChance + iAncientBoost + iEvolutionCount;
|
||||
|
||||
// Roll the dice (1-100)
|
||||
int iRoll = Random(100) + 1;
|
||||
|
||||
// Debug message to monitor rolls and chances
|
||||
if(DEBUG)
|
||||
{
|
||||
DoDebug("Evolution Check: Roll = " + IntToString(iRoll) + ", Chance = " + IntToString(iChance));
|
||||
}
|
||||
|
||||
// Check if the undead evolves
|
||||
if (iRoll <= iChance)
|
||||
{
|
||||
// Apply evolution template
|
||||
ExecuteScript("make_evolved", oUndead); // Apply template script
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
//:: Initialize Major Variables
|
||||
@@ -47,10 +85,6 @@ void main()
|
||||
object oSkelly;
|
||||
object oPC = GetFirstObjectInArea(oArea);
|
||||
|
||||
//:: Set threatlevel name text
|
||||
SetThreatLevel(OBJECT_SELF);
|
||||
|
||||
|
||||
//:: Check if the creature is an animal, beast, construct, or ooze, which should never carry treasure
|
||||
if (iRacial == RACIAL_TYPE_ANIMAL ||
|
||||
iRacial == RACIAL_TYPE_BEAST ||
|
||||
@@ -101,6 +135,17 @@ void main()
|
||||
{
|
||||
nAveragePCLevel = 2;
|
||||
}
|
||||
|
||||
//:: Setup Evolved Undead
|
||||
if(iRacial == RACIAL_TYPE_UNDEAD)
|
||||
{
|
||||
SetAge(OBJECT_SELF, d20(6));
|
||||
|
||||
EvolvedUndeadCheck(OBJECT_SELF);
|
||||
}
|
||||
|
||||
//:: Set threatlevel name text
|
||||
SetThreatLevel(OBJECT_SELF);
|
||||
|
||||
//:: Only active during Halloween week.
|
||||
if ((sMonthDay == "10/24") ||
|
||||
|
Reference in New Issue
Block a user