Yes, we're still using the default familar function. Here's our generic summon script, called for every summon spell (switches in the include differentiate spells):
#include "hg_inc"
#include "ac_spell_inc"
#include "nw_i0_generic"
#include "ac_effect_inc"
#include "fky_ai_locals"
#include "hgll_featreq_inc"
#include "subrace_inc"
#include "hg_epicspell_inc"
#include "fky_summon_inc"
void main() {
struct SpellInfo si = GetSpellInfo();
if (si.id < 0)
return;
si.id = GetSummoningItemReplacementSpellID(si.id, si.item);
if (SummonSpellAlternateUseCheck(si))
return;
if (GetIsQuasiclass(QUASIclass_ACCURSED_PARIAH, si.caster) && !GetIsObjectValid(si.item)) {
FloatingTextStringOnCreature("Shunned by all, you are unable to summon.", si.caster, FALSE);
return;
}
si.clevel = GetSummonSpellCasterLevel(si);
if (si.clevel < 1)
return;//Handles GetEpicActivationLevel returns for epics
float fDur = GetSummonSpellDuration(si);
int nVFX = GetSummonSpellVFX(si.id, si.caster);
struct SummonInfo sumnfo = GetSummonInfo(si);
if (GetLocalInt(si.caster, "DebugSummons")) {
string sDebug = "Summon Data: curlvl = " + IntToString(sumnfo.curlvl) + "; mod = " + IntToString(sumnfo.mod) +
"; env = " + IntToString(sumnfo.env) + "; res = '" + sumnfo.res + "';";
FloatingTextStringOnCreature(sDebug, si.caster, FALSE);
}
if (sumnfo.res != "")
SetSummonInts(si.caster, si.id, si.meta, sumnfo.curlvl, sumnfo.mod, sumnfo.env, sumnfo.rgskill);
else {
DebugSummon("ERROR: GetSummonInfo returned blank resref");
return;
}
if (si.id == SPELLABILITY_SUMMON_FAMILIAR) {
SummonFamiliar();
} else if (si.id == SPELLABILITY_SUMMON_ANIMAL_COMPANION) {
SummonAnimalCompanion();
} else {
effect eSummon = EffectSummonCreature(sumnfo.res, nVFX, sumnfo.delay, sumnfo.appearanim);
if (sumnfo.ex)
eSummon = ExtraordinaryEffect(eSummon);
if (sumnfo.exvfx)
DelayCommand(sumnfo.exvfxdelay,ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, EffectVisualEffect(sumnfo.exvfx),si.loc));
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eSummon, si.loc, fDur);
//DelayCommand(1.5+sumnfo.delay, ApplySummonModifiers(si, sumnfo.curlvl, sumnfo.mod, sumnfo.env, sumnfo.rgskill)); - now handled from onspawn of creature instead
}
}
As for your question about renewing usage, that's pretty easy to do. Just track it with a variable and reset as needed. Here are sample clips from our hellball code.
First, in onrest, we set the number of uses we want to allow via FeatLimit ints, and then delete the tracked uses since the last rest (here's a small chunk from the middle of the script):
if ((GetIsQuasiclass(QUASIclass_BLOODFIRE_MAGE, oPC) || GetIsQuasiclass(QUASIclass_DRAGONSTORM_MAGE, oPC)) &&
(nLevel = GetLevelIncludingLLs(class_TYPE_DRAGON_DISCIPLE, oPC)) >= 10)
SetLocalInt(oPC, "FeatLimit_" + IntToString(FEAT_EPIC_SPELL_HELLBALL), 1 + (nLevel / 10));
if (GetIsQuasiclass(QUASIclass_GNOMISH_INVENTOR, oPC) &&
GetLevelByclass(class_TYPE_WIZARD, oPC) >= 24) {
SetLocalInt(oPC, "FeatLimit_" + IntToString(FEAT_EPIC_SPELL_MAGE_ARMOUR), GetHitDiceIncludingLLs(oPC)/20);
SetLocalInt(oPC, "FeatLimit_" + IntToString(FEAT_EPIC_SPELL_HELLBALL), GetHitDiceIncludingLLs(oPC)/20);
}
if (GetKnowsFeat(FEAT_EPIC_SPELL_RUIN, oPC) &&
GetSkillRank(SKILL_SPELLCRAFT, oPC, TRUE) >= 50)
SetLocalInt(oPC, "FeatLimit_" + IntToString(FEAT_EPIC_SPELL_RUIN), 2);
DeleteLocalInt(oPC, "FeatUsed_" + IntToString(FEAT_DIVINE_WRATH));
DeleteLocalInt(oPC, "FeatUsed_" + IntToString(FEAT_EPIC_SPELL_HELLBALL));
DeleteLocalInt(oPC, "FeatUsed_" + IntToString(FEAT_EPIC_SPELL_RUIN));
DeleteLocalInt(oPC, "FeatUsed_" + IntToString(FEAT_EPIC_SPELL_MAGE_ARMOUR));
DeleteLocalInt(oPC, "FeatUsed_" + IntToString(FEAT_PDK_INSPIRE_1));
DeleteLocalInt(oPC, "FeatUsed_" + IntToString(FEAT_PDK_STAND));
DeleteLocalInt(oPC, "FeatUsed_" + IntToString(FEAT_PRESTIGE_INVISIBILITY_2));
DeleteLocalInt(oPC, "FeatUsed_" + IntToString(FEAT_WHOLENESS_OF_BODY));
That variable is then checked in the code executed by the feat in question, and operated on. Here's the hellball sample (I'm only showing the big for the Bloodfire Mage quasi):
AddLocalInt(OBJECT_SELF, "FeatUsed_" + IntToString(FEAT_EPIC_SPELL_HELLBALL), 1);
int nRemaining = GetLocalInt(OBJECT_SELF, "FeatLimit_" + IntToString(FEAT_EPIC_SPELL_HELLBALL)) -
GetLocalInt(OBJECT_SELF, "FeatUsed_" + IntToString(FEAT_EPIC_SPELL_HELLBALL));
if (nRemaining > 0) {
FloatingTextStringOnCreature("<c›þþ>You have " + IntToString(nRemaining) +
" uses of Hellball left.</c>", OBJECT_SELF, FALSE);
IncrementRemainingFeatUses(OBJECT_SELF, FEAT_EPIC_SPELL_HELLBALL);
}
As you can see, the feat gets incremented if they have uses remaining, otherwise it is left unset. Obviously, this approach will only work for feats with script access. Happily that is not an issue for nw_s2_familiar and nw_s2_animalcom.
Funky