For some reason, these forums tend to play havok with my copy/pasted code, so it may lose random carriage returns and such.This is mixed in with my meta-summons code that allows NPC's to summon without spells. We use it for everything from commoners with normal pets to wizards with familiars.There's bits of AI code for it in several scripts. OnRest checks to see if the metasummons should be unsummoned, for instance. I may not have time to find all of it before I leave for work.I can't take credit for this code. I've tweaked it over the years, but the code was originally from 'Legacy NWN', by Richard A Brooks. As far as I know. This system is no longer available for download. We use a lot of custom functions, so this won't work as it stands. If you need any of the custom functions for handling arrays or anything, let me know.
Notes from the Legacy NWN Manual:
Meta-Summoning is a form of simulated/emulated summoning that complements default/real summoning. It allows multiple allies of any template to be summoned at the same time. Even though they actually take up henchman slots, Meta-Summoned allies work exactly like true summoned creatures.To set up a Meta-Summoner that summons a single familiar/animal companion, just call Leg_AutoConfigureMetaSummonerForFOrAC in Leg_Hook_InitCreature. This function sets various Meta-Summoning variables automatically (see below under "Several variables...", and see the comment over 'lgcy_crt_spawn''s Leg_AutoConfigureMetaSummonerForFOrAC for more):Leg_AutoConfigureMetaSummonerFOrAC("nw_fm_ice","Ajax");Several variables may be set manually on a Meta-Summoner in Hook_InitCreature:
- SetLocalInt(OBJECT_SELF,LEG_VAR_METASUM_FAKE_SPELL,
SPELL_SUMMON_CREATURE_IV);This gives the ID of the spell the creature will appear to be casting as it's really using its Meta-Summoning ability, which is a Somatic Magical ability. A value of -1 means the creature can summon allies instantly. If left unset, the default value is SPELL_ACID_FOG/0.
- SetLocalInt(OBJECT_SELF,LEG_VAR_METASUM_VERBAL,TRUE);A Verbal Meta-Summoning ability will be unuseable if the Meta-Summoner is Silenced or Polymorphed. If left unset, the default value is FALSE.
- SetLocalInt(OBJECT_SELF,LEG_VAR_METASUM_VEFFECT,
VFX_FNF_SUMMON_UNDEAD);A Fire-And-Forget visual effect that'll be played over the location where an ally spawns in. Set to -1 to indicate there should be no effect. Spawning delays are automatically added when effects needing them are used:EffectDelayVFX_FNF_UNDEAD_DRAGON5.0VFX_FNF_SUMMON_CELESTIAL4.0VFX_FNF_SUMMON_GATE4.0VFX_FNF_SUMMONDRAGON1.0If LEG_VAR_METASUM_VEFFECT is set to the special value of -100, Meta-Summoned allies will appear to fly in from above. If it's left unset this variable's default value is VFX_FNF_SUMMON_MONSTER_1.
- SetLocalInt(OBJECT_SELF,LEG_VAR_METASUM_MAX_USES,10);The number of uses of the Meta-Summoning ability per rest cycle. Meta-Summoning 1 creature always costs 1 use. If left unset the default value is 1.
- SetLocalInt(OBJECT_SELF,LEG_VAR_METASUM_MAX_USES_PER_ROUND,6);The maximum number of allies the Meta-Summoner may summon simultaneously. If left unset the default value is 1.
- SetLocalInt(OBJECT_SELF,LEG_VAR_METASUM_MIN_USES_PER_ROUND,4);The minimum number of allies the Meta-Summoner must summon simultaneously. If unable to summon at least this many new allies, the Meta-Summoner won't be able to use his ability that round. If left unset the default value is 1.
- SetLocalInt(OBJECT_SELF,LEG_VAR_METASUM_MAX_SUMMONED,10);The maximum number of Meta-Summoned allies the Meta-Summoner may have following him at a time. If left unset, the default value is 1.
- SetLocalInt(OBJECT_SELF,LEG_VAR_METASUM_SURVIVE_REST,TRUE);Whether Meta-Summoned allies should remain summoned when the Meta-Summoner starts resting. If left unset, the default is FALSE.
- SetLocalFloat(OBJECT_SELF,LEG_VAR_METASUM_MAX_RANGE,
fSPELL_RANGE_LONG);This is the equivalent of a spell range for the Meta-Summoning ability. If the value is 0.0 the Meta-Summoner will only be able to summon allies directly adjacent to itself. If the special value of -1.0 is used, allies will be summoned at random valid locations within a 10 x 10 m square field centered over the Meta-Summoner. Legacy effectively forces this to -1.0 when LEG_VAR_METASUM_VEFFECT is set to a visual effect requiring a delay (see above under "Spawning delays..."). If left unset the default value is 0.0.
- familiars or animal companions respectively. If left unset the default value is 1.
- SetLocalFloat(LEG_VAR_METASUM_LIFESPAN,300.0);If > 0.0, sets that any Meta-Summoned allies should be unsummoned after this many seconds go by. If left unset the default value is 0.0.
OnSpawn
// This function, designed for use in Hook_InitCreature, initializes a// Meta-Summoner which summons a single familiar/animal companion. When the
// default F/AC templates (see "default base resref strings..." below) are used
// with Meta-Summoning, Legacyautomatically summons a F/AC of the appropriate
// level ex. a level 10 NPC will summon a level 10 F/AC.
//// If sName is "", the F/AC's name will be left at the default template name
// ex. "Hawk Companion".
//// If bAnimalComp is TRUE, the summoned creature will be an animal companion,
// otherwise it'll be a familiar. The group it was originally intended for (see
// "Group" below) is _always_ overridden by bAnimalComp.
////// The default base resref strings are:
//// Name Group Base Resref
//// Badger Companions nw_ac_badger
// Brown Bear Companions nw_ac_bear
// Boar Companions nw_ac_boar
// Dire Rat Companions x0_ac_drat0
// Dire Wolf Companions nw_ac_dwlf
// Hawk Companions nw_ac_hawk
// Panther Companions nw_ac_pant
// Giant Spider Companions nw_ac_spid
// Wolf Companions nw_ac_wolf
//// Bat Familiars nw_fm_bat
// Faery Dragon Familiars x0_fm_fdrg
// Fire Mephit Familiars nw_fm_fire
// Hell Hound Familiars nw_fm_hell
// Ice Mephit Familiars nw_fm_ice
// Imp Familiars nw_fm_imp
// Panther Familiars nw_fm_crag
// Pixie Familiars nw_fm_pixi
// Pseudodragon Familiars x0_fm_pdrg0
// Raven Familiars nw_fm_rave
// Eyeball Familiars x2_fm_eye0////
void Leg_AutoConfigureMetaSummonerForForAC(string sBaseTemplate,string sName="",int bAnimalComp=FALSE);
void Leg_AutoConfigureMetaSummonerForForAC(string sBaseTemplate,string sName="",int bAnimalComp=FALSE)
{
SetLocalInt(OBJECT_SELF,"SPAWN_META_SUMMONER",TRUE); SetLocalInt(OBJECT_SELF,"METASUM_FAKE_SPELL", SPELLABILITY_SUMMON_FAMILIAR);
SetLocalInt(OBJECT_SELF,"METASUM_SURVIVE_REST",TRUE);
if(bAnimalComp)
SetLocalInt(OBJECT_SELF,"METASUM_OVERRIDE_SUMMON_TYPE",3);
else
SetLocalInt(OBJECT_SELF,"METASUM_OVERRIDE_SUMMON_TYPE",2);
SetLocalInt(OBJECT_SELF,"METASUM_VEFFECT",VFX_FNF_SUMMON_UNDEAD); Leg_AppendToLocalStringArray(OBJECT_SELF,"METASUM_TEMPLATE_ARRAY", sBaseTemplate); SetLocalString(OBJECT_SELF,"METASUM_FAC_NAME",sName);
}
From the combat AI// Meta-Summoning was added in response to a suggestion made by Craig Baker
// that Legacy should have a feature akin to Olander's AI's Spawn Hordes.
int Leg_TalentMetaSummon()
{
if ( GetLocalInt(OBJECT_SELF,"SPAWN_SUMMONED")>0 || !Leg_DeleteTimePoint("NO_SUMMONING_TIMER", nNO_SUMMONING_TIMER_LENGTH) || ( GetLocalInt(OBJECT_SELF,"METASUM_VERBAL") && (GetLocalInt(OBJECT_SELF,"STATE_SILENCED") || GetLocalInt(OBJECT_SELF,"STATE_POLYMORPHED")) ) ) return FALSE;
//if(bDBG_COMBAT_ON) Leg_DbgMsg(sDBG_INDENT1+"Leg_TalentMetaSummon");
location lTarget = GetLocation(OBJECT_SELF);
float fMaxRange = GetLocalFloat(OBJECT_SELF,"METASUM_MAX_RANGE");
int nUsesLeft = GetLocalInt(OBJECT_SELF,"METASUM_CUR_USES");
int nMinUsesPerRound = GetLocalInt(OBJECT_SELF, "METASUM_MIN_USES_PER_ROUND"); if(nUsesLeft==0 || nUsesLeft<nMinUsesPerRound) return FALSE;
int nSummonVis = GetLocalInt(OBJECT_SELF,"METASUM_VEFFECT");
float fDelay;
switch(nSummonVis)
{
case VFX_FNF_UNDEAD_DRAGON: fDelay = 5.0; break;
case VFX_FNF_SUMMON_CELESTIAL:
case VFX_FNF_SUMMON_GATE: fDelay = 4.0; break;
case VFX_FNF_SUMMONDRAGON: fDelay = 1.0; break;
}
if(fDelay==0.0 && fMaxRange==-1.0) fDelay = 0.1;
// Count how many summoneds the creature currently has.
int nCurSummoned;
int nMaxSummons = GetLocalInt(OBJECT_SELF,"METASUM_MAX_SUMMONED");
int nNth = 1;
object oHench = GetHenchman(OBJECT_SELF,nNth);
while(oHench!=OBJECT_INVALID)
{
if(GetLocalInt(oHench,"SPAWN_SUMMONED")>0)
nCurSummoned++;
oHench = GetHenchman(OBJECT_SELF,++nNth);
}
if(nMaxSummons-nCurSummoned<nMinUsesPerRound) return FALSE;
int nFakeSpell = GetLocalInt(OBJECT_SELF,"METASUM_FAKE_SPELL");
if(nFakeSpell>-1 && nUsesLeft>0 && nCurSummoned<=nMaxSummons) ActionCastFakeSpellAtLocation(nFakeSpell,lTarget);
location lTarget2;
int nUsedThisRound;
int nMaxUsesPerRound = GetLocalInt(OBJECT_SELF, "METASUM_MAX_USES_PER_ROUND"); while(nUsesLeft>0 && nUsedThisRound<nMaxUsesPerRound && nCurSummoned<=nMaxSummons)
{
if(fDelay>0.0)
{
lTarget2 = Leg_CreateRandomTestedLocation(lTarget,0.0,10.0,0.0,3, 1.0,99.9,TRUE); if(GetAreaFromLocation(lTarget2)==OBJECT_INVALID)
lTarget2 = lTarget;
ActionDoCommand(ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(nSummonVis),lTarget2));
if(nSummonVis==-100)
ActionDoCommand(DelayCommand(fDelay, Leg_MetaSummon(lTarget2,-100)));
else
ActionDoCommand(DelayCommand(fDelay, Leg_MetaSummon(lTarget2,-1)));
}
elseActionDoCommand(Leg_MetaSummon(lTarget,nSummonVis));
nCurSummoned++;
nUsedThisRound++;
nUsesLeft--;
}
if(fDelay>0.0)
SetLocalInt(OBJECT_SELF,"NO_SUMMONING_TIMER",Leg_GetTimePoint()); ActionDoCommand(SetLocalInt(OBJECT_SELF,"METASUM_CUR_USES", nUsesLeft));
// Blocking action.
if(nFakeSpell>-1) return TRUE;
// Non-blocking action.
return FALSE;
}
void Leg_MetaSummon(location lTarget,int nSummonVis)
{
string sTemplate = Leg_Hook_GetMetaSummonedTemplate();
object oNew;
if(nSummonVis==VFX_FNF_SUMMON_CELESTIAL || nSummonVis==VFX_FNF_SUMMON_GATE)
{
oNew = CreateObject(OBJECT_TYPE_CREATURE,LEG_RES_LOCATION_TESTER, lTarget);
lTarget = GetLocation(oNew);
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(nSummonVis),lTarget); DestroyObject(oNew,1.0);
DelayCommand(4.0,Leg_MetaSummon(lTarget,-1));
return;
}
if(FindSubString(sTemplate,"_ac_")>-1 || FindSubString(sTemplate,"_fm_")>-1)
{
int nHD = GetHitDice(OBJECT_SELF);
string sSuffix = IntToString(nHD);
if(nHD<10) sSuffix = "0"+sSuffix;
sTemplate += sSuffix;
}
oNew = Leg_CreateObject(OBJECT_TYPE_CREATURE,sTemplate,lTarget);
string sFACName = GetLocalString(OBJECT_SELF,"METASUM_FAC_NAME"); if(sFACName!="")
SetName(oNew,sFACName);
else
{
string sName = GetName(oNew);
if(FindSubString(sName,"Summoned")==-1)
SetName(oNew,"Summoned "+sName);
}
if(nSummonVis>-1)
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(nSummonVis),GetLocation(oNew)); else if(nSummonVis==-100)
ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectAppear(),oNew); SetLocalInt(oNew,"SPAWN_SUMMONED", GetLocalInt(OBJECT_SELF,"METASUM_OVERRIDE_SUMMON_TYPE")); Leg_AddHenchman(OBJECT_SELF,oNew);
float fLifespan = GetLocalFloat(OBJECT_SELF,"METASUM_LIFESPAN");
if(fLifespan>0.0)
AssignCommand(oNew,DelayCommand(fLifespan,Leg_Unsummon()));
}
int Leg_GetHasMetaSummonedAC()
{
if(!GetLocalInt(OBJECT_SELF,"SPAWN_META_SUMMONER"))
return FALSE;
int nNth = 1;
object oHench = GetHenchman(OBJECT_SELF,nNth);
while(oHench!=OBJECT_INVALID)
{
if(GetLocalInt(oHench,"SPAWN_SUMMONED")==3) return TRUE;
oHench = GetHenchman(OBJECT_SELF,++nNth);
}
return FALSE;}
Modifié par wyldhunt1, 31 décembre 2011 - 09:12 .