Add Shadow Servant and unarmed system updates
Fixed a bunch of TLK typos. Updated Master of Shadow's Shadow Servant. Added Maul to the Metal Domain feat choice. Drider is a large creature. Added missing Eagle Claw base weapon. Tentatively fixed NUI spell selector hang issue. Fixed Monk / Shou / IoDM die increasing bug. Added StepDie() function to progressively increase Monster damage constants. Clamped Skill increases to 128 in json_AdjustCreatureSkillByID Updated PRC8 Tester module to have new weapon types. Added all spell focus feats to Wizard's bonus feat list. Updated PRC8 manual. Added notes.
This commit is contained in:
168
Notes/mshdw_shadserv.nss
Normal file
168
Notes/mshdw_shadserv.nss
Normal file
@@ -0,0 +1,168 @@
|
||||
//::////////////////////////////////////////////////////////
|
||||
//:: ;-. ,-. ,-. ,-.
|
||||
//:: | ) | ) / ( )
|
||||
//:: |-' |-< | ;-:
|
||||
//:: | | \ \ ( )
|
||||
//:: ' ' ' `-' `-'
|
||||
//::///////////////////////////////////////////////////////
|
||||
//::
|
||||
/*
|
||||
Impactscript for Shadow Servant.
|
||||
(this is handled in the Familiar script)
|
||||
|
||||
Shadow Servant (Su): At 1st level, your shadow familiar permanently
|
||||
transforms into a Medium shadow elemental. It loses all familiar
|
||||
traits, but gains new abilities as your shadow servant.
|
||||
|
||||
Should your shadow servant die, you can summon a replacement after
|
||||
24 hours pass. Your shadow servant cannot travel farther from you
|
||||
than 30 feet + 10 feet for each of your master of shadow levels
|
||||
(40 feet at 1st level and a maximum of 130 feet at 10th level). If
|
||||
it is forcibly separated from you by more than this distance, the
|
||||
servant dissipates instantly, and you must wait 24 hours to summon
|
||||
a new one.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Script: mshadw_shadserv.nss
|
||||
//:: Author: Jaysyn
|
||||
//:: Created: 2025-11-11 19:25:58
|
||||
//:://////////////////////////////////////////////
|
||||
#include "prc_inc_json"
|
||||
#include "prc_inc_spells"
|
||||
|
||||
const string SHADOW_SERVANT_RESREF = "prc_shadow_serv";
|
||||
|
||||
// Watch function: despawns Shadow Servant if master is dead or out of range
|
||||
void ShadowServantWatch(object oShadow, object oPC)
|
||||
{
|
||||
if(DEBUG) DoDebug("mshadw_shadserv >> ShadowServantWatch: Starting function.");
|
||||
|
||||
int nMaster = GetLevelByClass(CLASS_TYPE_MASTER_OF_SHADOW, oPC);
|
||||
|
||||
float fRange = 30.0 + (nMaster * 10);
|
||||
|
||||
if (!GetIsObjectValid(oShadow) || !GetIsObjectValid(oPC)) return;
|
||||
|
||||
if (GetIsDead(oPC) ||
|
||||
GetDistanceBetween(oShadow, oPC) > FeetToMeters(fRange))
|
||||
{
|
||||
DestroyObject(oShadow);
|
||||
return;
|
||||
}
|
||||
|
||||
DelayCommand(1.0, ShadowServantWatch(oShadow, oPC));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPC = OBJECT_SELF;
|
||||
|
||||
int nMaster = GetLevelByClass(CLASS_TYPE_MASTER_OF_SHADOW, oPC);
|
||||
|
||||
int nDexBonus = (nMaster >= 5 && (nMaster % 2)) ? (nMaster - 3) : 0;
|
||||
|
||||
float fRange = 30.0 + (nMaster * 10);
|
||||
|
||||
// Target location
|
||||
location lTarget = GetSpellTargetLocation();
|
||||
|
||||
// Distance check
|
||||
if (GetDistanceBetweenLocations(GetLocation(oPC), lTarget) > FeetToMeters(fRange))
|
||||
{
|
||||
SendMessageToPC(oPC, "That location is too far away.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Load template
|
||||
json jShadow = TemplateToJson(SHADOW_SERVANT_RESREF, RESTYPE_UTC);
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: TemplateToJson failed <20> bad resref or resource missing.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Original HD
|
||||
int nOriginalHD = json_GetCreatureHD(jShadow);
|
||||
if (nOriginalHD <= 0)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_GetCreatureHD failed <20> template missing HD data.");
|
||||
return;
|
||||
}
|
||||
|
||||
//:: Add Hit Dice
|
||||
int nHDToAdd = nMaster -1;
|
||||
|
||||
if (nHDToAdd < 0) nHDToAdd = 0;
|
||||
|
||||
jShadow = json_AddHitDice(jShadow, nHDToAdd);
|
||||
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_AddHitDice failed - JSON became invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
//:: Update feats
|
||||
jShadow = json_AddFeatsFromCreatureVars(jShadow, nOriginalHD);
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_AddFeatsFromCreatureVars failed <20> JSON became invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
//:: Update stats
|
||||
jShadow = json_ApplyAbilityBoostFromHD(jShadow, nOriginalHD);
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_ApplyAbilityBoostFromHD failed <20> JSON became invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
//:: Bonus DEX from Shadow Servant class ability
|
||||
jShadow = json_UpdateTemplateStats(jShadow, 0, nDexBonus);
|
||||
|
||||
// Size increase
|
||||
if (nMaster > 2)
|
||||
{
|
||||
jShadow = json_AdjustCreatureSize(jShadow, 1, TRUE);
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_AdjustCreatureSize failed - JSON became invalid.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
object oShadow = JsonToObject(jShadow, lTarget);
|
||||
effect eSummon = ExtraordinaryEffect(EffectSummonCreature("", VFX_FNF_SUMMON_UNDEAD, 0.0, 0, VFX_IMP_UNSUMMON, oShadow));
|
||||
|
||||
ApplyEffectAtLocation(DURATION_TYPE_PERMANENT, eSummon, lTarget);
|
||||
|
||||
if (!GetIsObjectValid(oShadow))
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: JsonToObject failed - could not create creature from edited template.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set faction to caster<65>s
|
||||
ChangeFaction(oShadow, oPC);
|
||||
SetLocalObject(oShadow, "ANIMATOR", oPC);
|
||||
|
||||
SetCurrentHitPoints(oShadow, GetMaxPossibleHP(oShadow));
|
||||
|
||||
effect eGhost = EffectVisualEffect(VFX_DUR_GHOST_TRANSPARENT);
|
||||
eGhost = UnyieldingEffect(eGhost);
|
||||
|
||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, oShadow);
|
||||
|
||||
// Full round wait then move
|
||||
AssignCommand(oShadow, ClearAllActions());
|
||||
AssignCommand(oShadow, ActionWait(6.0));
|
||||
AssignCommand(oShadow, ActionMoveToObject(oPC));
|
||||
|
||||
// Start watch loop
|
||||
DelayCommand(6.1, ShadowServantWatch(oShadow, oPC));
|
||||
}
|
||||
Reference in New Issue
Block a user