Author Topic: NPCs with Familiars and Animal Companions  (Read 1335 times)

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« on: December 31, 2011, 02:07:00 am »


                What is the trick to defining an NPCs animal companion or familiar in the toolset?
               
               

               
            

Legacy_wyldhunt1

  • Sr. Member
  • ****
  • Posts: 443
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« Reply #1 on: December 31, 2011, 03:49:48 am »


               If no one else answers before I get a chance, I'll check my old code and see how it worked.
The default AI will never use their companions though. You'd need to add that functionality yourself or use one of the pre-made custom AI's.
If I remember correctly, my AI (Custom) used a variable set on the mage to define their familiar/companion.
I'll check the script and see if I can grab the code for the summoning and setting as a familiar/companion for you.
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« Reply #2 on: December 31, 2011, 04:13:45 am »


               Hopefully what wyldhunt said above will work.   After taking a quick look, Most of it looked hard coded to me.   I seen no way to set the Animal-companion/familiar outside of the leveling process.  To make the Animal/familiar companion availaible to the level up process would need 2da edits to hen_familiar.2da and hen_companion.2da.

The BASERESREF collumn in each 2da would refferance the buleprint for each level of the creature with the 2 digit level of the owner appended to the end. 

example:
BASERESREF of  NW_AC_BADGER would referr to

NW_AC_BADGER01
NW_AC_BADGER02
...
NW_AC_BADGER40

Perhaps nwnx has a way to set the companions, I do not know.

Refferance used in responce.
Resource.Creatures - Familiars
Function Category - Henchmen/Familiars/Summoned
Hen companion.2da - NWNWiki, the Neverwinter Nights Wiki - your ...
Hen familiar.2da - NWNWiki, the Neverwinter Nights Wiki - your ...
               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« Reply #3 on: December 31, 2011, 02:33:15 pm »


               Thanks for pointing me in the right direction. I'd like to see those old scripts if you can find them, Wyldhunt. Setting local variables makes sense for identifying Familiar name and type.
               
               

               
            

Legacy_wyldhunt1

  • Sr. Member
  • ****
  • Posts: 443
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« Reply #4 on: December 31, 2011, 04:24:32 pm »


                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 .
                     
                  


            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« Reply #5 on: December 31, 2011, 05:36:56 pm »


                <pointing to an old...>

69MEH69 wrote some pretty good henchmen/companion stuff in his Module Builder's Henchman Kit:

from the description
...the multiplehenchmen ERF has multiple henchman support, inventory control and advanced henchman AI, the monsterAI ERF is an advanced monster AI. I have included a HowTo for adding familiars and/or animal companions for henchmen and NPCs...

I've been playing around with some parts of it. I do recommend looking at it.

<...overgrown trail into the wilds>
               
               

               


                     Modifié par Rolo Kipp, 31 décembre 2011 - 05:37 .
                     
                  


            

Legacy_wyldhunt1

  • Sr. Member
  • ****
  • Posts: 443
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« Reply #6 on: December 31, 2011, 05:51:40 pm »


               69MEH69's stuff may be easier than picking apart our systems.

It's difficult to take one item out of our AI.
I made a quick edit to my post above and added in some carriage returns since they all got stripped out.
If you have any questions on it, or if you need to see how the functions are used, let me know.
               
               

               
            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« Reply #7 on: December 31, 2011, 06:03:07 pm »


               <looking up...>

wyldhunt1 wrote...
69MEH69's stuff may be easier than picking apart our systems.

It's difficult to take one item out of our AI.
...

May be easier, but I'm a lot more interested in *flexibility* :-)
I'm liking the core concepts of your Legacy meta-summoning.

I did a similar (non-magical summoning of multiple allies), one-shot script for summoning pack members. Packmember ResRef was stored as a local string on the Alpha.  Thus Alpha wolfen calls pack wolfen, Alpha stag calls herd of deer, Alpha Scraggen calls murder of land pirhana ;-)

I like your more complicated, but considerably more flexible *system* of meta-summoning a lot better. Normal NPC pets? Hoo-boy! 

<...from intense study>
               
               

               


                     Modifié par Rolo Kipp, 31 décembre 2011 - 06:03 .
                     
                  


            

Legacy_wyldhunt1

  • Sr. Member
  • ****
  • Posts: 443
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« Reply #8 on: December 31, 2011, 06:29:42 pm »


               I don't think I have the original Legacy NWN rar that I downloaded, but I do have the erf and instruction book. I'm fairly sure that's all that it had. Legacy is the base for most of our systems. I've had to tweak a lot of it because it was prone to TMI's in large PW's. However, most of it was stable from the start. It was the basis for the zone system and a lot of our NPC AI.

If you want it, I can send it to you to pick apart.

EDIT:
   Rolo:
      I dropped it in your Drop Box.
   If anyone else wants a copy, let me know.
               
               

               


                     Modifié par wyldhunt1, 31 décembre 2011 - 06:35 .
                     
                  


            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« Reply #9 on: December 31, 2011, 06:33:09 pm »


               <grins in...>

wyldhunt1 wrote...
I don't think I have the original Legacy NWN rar that I downloaded, but I do have the erf and instruction book. I'm fairly sure that's all that it had. Legacy is the base for most of our systems. I've had to tweak a lot of it because it was prone to TMI's in large PW's. However, most of it was stable from the start. It was the basis for the zone system and a lot of our NPC AI.

If you want it, I can send it to you to pick apart.

You bet! :-) Drop it in the dropbox? I'm @ *B and it's a good time to D/L... but I'll be back tomorrow, so that will work also :-)

Edit: You're *fast*! :-) Got it.

<...unalloyed delight>
               
               

               


                     Modifié par Rolo Kipp, 31 décembre 2011 - 06:36 .
                     
                  


            

Legacy_wyldhunt1

  • Sr. Member
  • ****
  • Posts: 443
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« Reply #10 on: December 31, 2011, 06:36:28 pm »


               Done
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« Reply #11 on: December 31, 2011, 06:52:32 pm »


               I dont think NWNX can do anything with this as since its possible to make creature to use summon animal/familiar and actually summon something but it will be always badger or bat without name as creatures doesn't suppport corresponding fields in GFF structure. Even if you try to add them, engine won't use them.

if anyone want to know how to make creature use summon familiar/animal feat correctly, let me know (it consist from few server-side 2DA changes), then you only need to change the spellscript and ensure special behavior for creatures
               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« Reply #12 on: December 31, 2011, 07:29:10 pm »


               ShaDoOoW that sounds like what we are talking about. Spill those beans!
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« Reply #13 on: December 31, 2011, 07:47:53 pm »


               To do it - you need to change spells.2da, rows 317 and 318, collumns Category -> 16 and UserType -> 2
this will make summon animal companion/familiar selectable under Special Abilities tab (feat when used make creature stucked) and AI will recognize it as if it were aura-like ability

that should be it, by default creature wont summon anything unless correct class (druid/ranger, wiz/sorc) however since it doesnt work properly and summon always unnamed badger/bat you dont have to put creature these classes and rather change the summon animal companion/familiar spellscript to summon specific creature.
               
               

               
            

Legacy_nwnsmith

  • Full Member
  • ***
  • Posts: 125
  • Karma: +0/-0
NPCs with Familiars and Animal Companions
« Reply #14 on: October 31, 2013, 06:33:20 pm »


               Was Rolo or anyone else able to get this working. I would like to add an ability for my NPCs to summon companions and escorts.

ShaDoWoW's version also looks interesting.