Setup onSpawn Evolved Undead template. Started baseitem work for new iprop forge system. Full compile. Updated release archive.
174 lines
5.3 KiB
Plaintext
174 lines
5.3 KiB
Plaintext
/* 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(){} |