Author Topic: SummonPack v0.3 :-P  (Read 351 times)

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
SummonPack v0.3 :-P
« on: August 21, 2011, 08:03:27 pm »


                <Howling...>

I knew it! Just knew it! 

As soon as I got time (and juice) to work on scripting, gremlins would come sit on my shoulder :-(

The following script is set on the x2_special_combat_ai_script variable of my wolfen henchman.

It (supposedly) should:
  • Return if pack has already been summoned
  • Set up variables (current target, targets location, etc.)
  • Play a sound (variable on henchman)
  • Look for a valid location around (absurdly close to) target
  • create a copy of packmember creature (blueprint resref stored on henchman)
  • Repeat 4 & 5 nPackLevel times...
  • Set boolean that pack has been summoned
  • Turn off henchman AI on round she summons pack
Of course, it doesn't do any of that... and my battery is low :-(

Please look over this bit and heap advice (and scorn, if you really enjoy that sort of thing :-) on my head.


#include "nw_i0_generic"
#include "nw_i0_2q4luskan"

const string sbCont =  "X2_SPECIAL_COMBAT_AI_SCRIPT_OK";

void main()
{
  //NPC Summon Pack

  // IF bPackSummoned is true, return
  if (GetLocalInt(OBJECT_SELF,"bPackSummoned") == TRUE) return;

  //Get NPC's target and other variables
  int nPackLevel = GetLocalInt(OBJECT_SELF,"nPackLevel");
  string sPackType = GetLocalString(OBJECT_SELF,"sPackType"); //Creature name
  object oCurrTarget =GetLocalObject(OBJECT_SELF,"X2_NW_I0_GENERIC_INTRUDER");
  location lTargetLoc = GetLocation(oCurrTarget);
  float fRadius; //Random distance from oCurrTarget
  float fDir; //Random direction from oCurrTarget

  // Play summoning sound
  PlaySound(GetLocalString(OBJECT_SELF,"sSummonSound"));

   // For each nPackLevel, create a packmember of sPackType out of sight
  int nPackNum = nPackLevel;
  int nObjectType = OBJECT_TYPE_CREATURE; // Object type to create
  int bUseAppearAnimation = FALSE;
  int y;
  location lInSpot;

  while (nPackNum--) // Runs at least once, decrements
  {
    // Find a distant spot to place new member
    lInSpot = GetLocation(OBJECT_INVALID); // clear the location variable
    int nNumTries  = 26; // max loops for random test
    fRadius    = IntToFloat(Random(20)/10+1); // Should be rnd(20m)+10m
    fDir      = IntToFloat(Random(36)*10); // 0 to 350 degrees
    y = nNumTries;

    while (y--) // Runs at least once, decrements
    {
      // Generate a location
      lInSpot = GenerateNewLocationFromLocation(lTargetLoc, fRadius, fDir, fDir);
      if (lInSpot != GetLocation(OBJECT_INVALID))
      {
        // YES! we found a valid location... can it reach target?
        // pathfinding validation here

        // Create copy of sPackType at lInSpot, delayed by (nPackLevel*3 seconds)
        DelayCommand((3.0f*nPackLevel), CreateObjectVoid(nObjectType, sPackType, lInSpot, FALSE));
        y = 0;
      }
    }
  }
  //set SummonedPack variable on Summoner
  SetLocalInt(OBJECT_SELF,"bPackSummoned", TRUE);

  // Stop the rest of the Combat AI From Running. SummonPack will use up first round.
  SetLocalInt(OBJECT_SELF,sbCont,TRUE);
}


Edit: Stoopid formatting :-P

<...in despair>
               
               

               


                     Modifié par Rolo Kipp, 23 août 2011 - 08:13 .
                     
                  


            

Legacy_Hardcore UFO

  • Full Member
  • ***
  • Posts: 157
  • Karma: +0/-0
SummonPack v0.3 :-P
« Reply #1 on: August 21, 2011, 08:39:13 pm »


               Is it just me or is there not an original creature created for the others to be copied from?
               
               

               
            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
SummonPack v0.3 :-P
« Reply #2 on: August 22, 2011, 05:43:08 pm »


               <Tosses a coin...>

Hardcore UFO wrote...

Is it just me or is there not an original creature created for the others to be copied from?


The string sPackType = GetLocalString(OBJECT_SELF,"sPackType"); //Creature name Gets the blueprint resref from the summoner... supposedly :-P

Found the first problem, though... I'm using MBHK & the Battle AI from the vault. MBHK calls hench_i0_ai for DetermineCombatRound, and the Battle AI (which I rather love, otherwise) had removed the SPECIAL_COMBAT_AI hook.  Put that back in and at least the script is firing.

But working it out (on paper) last night, several things bugged me. So I flipped the script.

The summoner will create nPackLevel pathfinding creatures (rk_searcher - invis, plot, only spawn & death scripts). Each of these will face a random direction and run like hell (DM speed). Then they kamikaze, creating a packmember when and where they expire.  Which creatures to create and certain other info is handed off from summoner to searcher. Then from searcher to packmember. Packmember levels up, then heads back to summoner's target (if still alive) or last target position.

This way the summons is fire & forget, every created packmember not only shows up in a valid location, but with a confirmed path back to target. It also adds the possibility of your friends sucking more hostiles into combat... I like that. TANSTAAFL.

Later I'll put conditionals on it so the summons only occurs in outside&&natural areas, and only if the summoner feels a bit overwhelmed.

I'll post the new set of scripts when I have something decent :-P

As always, I really do read and appreciate review :-)
And if you see something, please let me know, whether it's an error, or just an inefficient algorithm.  I especially like in-depth post-mortems with examples :-)

<...and flips the script>
               
               

               


                     Modifié par Rolo Kipp, 22 août 2011 - 04:44 .
                     
                  


            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
SummonPack v0.3 :-P
« Reply #3 on: August 23, 2011, 08:56:13 pm »


                <looks over his lenses...>

This works pretty good :-)

Set up a bound & gagged aspect of Lolth and logged in a 27th level berzerker (Skeaver... my only character crazy enough :-/ Skeaver made friends with the alpha wolfen who promptly level up to 26th ranger. So far, nothing special except the distant muffled shrieks of a demon-goddess. Sauntered over to the druid's grove (giggling a little) and my henchwolfen, Fidelea "*DON'T* call me Fido!" Swiftpaw promptly yelled "To Battle!" and fired off a few arrows... which did absolutely nothing against Lolth's AC 66.

Right after Fidelea switched to melee and charged in, the first of her 13 level 13 wolfen ranger friends showed up. Fidelea died a gruesome death about three rounds later, but the pack kept arriving. Arriving, shooting arrows, seeing it was useless and charging in and dying.

I'm afraid Skeaver thought it was something of a hoot :-(

But the pack melting out of the woods was about as slick as the Exxon Valdez :-)

Still have to work on the *UN* summoning part and resetting the summoner's "I can summon again" flag.  
Where is a good spot to do something with "GetIsInCombat"? When combat is over, I want all my buddies to go away...

Ok, here are the summoning scripts in four parts and a prelude:  
  • rk_searcher: You will need a default pathfinding creature. Called mine rk_searcher and gave it a sprite appearance for debugging. It's invis now, but it was cool watching those little creatures buzz off in a trail of (fairy) dust!
  • packmember: You will need a default packmember creature, set up like henchmen in the MBHK (clean lvl 1)
  • Variables: Your alpha creature, the summoner, will need:
  • string X2_SPECIAL_COMBAT_AI = rk_summonpack
  • string sPackType = packmember // ResRef of the packmember creature
  • string sSummonSound = as_an_wolfhowl1 //the ResRef of the sound you want them to scream
  • int nPackLevel = min. packlevel
  • int bPackSummoned = 0 // FALSE
That's all the set up needed... 

Note: change the PackType to bouncer and the sound to a feminine shriek and place on a barmaid and you'll have an instant bar brawl...

<...and ducks>
               
               

               
            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
SummonPack v0.3 :-P
« Reply #4 on: August 23, 2011, 08:58:04 pm »


                This is rk_summonpack:

Suggestions appreciated!


/*  rk_summonpack
        v0.3
    by Rolo Kipp   */
void main()
{
//NPC Summon Pack

// IF bPackSummoned is true, return
if (GetLocalInt(OBJECT_SELF,"bPackSummoned") == TRUE) return;
//Get NPC's target and other variables
int nPackLevel = GetLocalInt(OBJECT_SELF,"nPackLevel"); // Minimum packlevel from summoner
int nHD = (GetHitDice(OBJECT_SELF))/2; //PackLevel is half of summoner level
if (nHD >nPackLevel) nPackLevel = nHD;  // Whichever is higher

string sSearcherType = "rk_searcher";
string sPackType = GetLocalString(OBJECT_SELF,"sPackType"); //Packmember ResRef stored on summoner
object oEnemy =GetLocalObject(OBJECT_SELF,"X2_NW_I0_GENERIC_INTRUDER");
location lTargetLoc = GetLocation(oEnemy); // Location of enemy
// Play summoning sound
PlaySound(GetLocalString(OBJECT_SELF,"sSummonSound")); // Play sound defined on creature
SpeakString("To Battle!"); // My kinda angel :-)

// For each nPackLevel, create a pathfinder
int x=0;
string sSearcherTag; // Declare string for tag generation - not used yet
while (x<nPackLevel)
   {
     sSearcherTag = sSearcherType+IntToString(x+1);
     object oSearcher = CreateObject(OBJECT_TYPE_CREATURE, sSearcherType, lTargetLoc, TRUE, sSearcherTag);
     SetLocalString(oSearcher,"sPackType",sPackType);
     SetLocalInt(oSearcher,"nPackLevel",nPackLevel);
     SetLocalObject(oSearcher,"oEnemy",oEnemy); // Store current target on searcher
     SetLocalLocation(oSearcher,"lTargetLoc",lTargetLoc); // Store target location in case it dies before spawn
     x++;
   }

//set SummonedPack variable on Summoner
SetLocalInt(OBJECT_SELF,"bPackSummoned", TRUE);
}



Arrrrrgggg! Can someone tell me how to post here without losing formatting?
               
               

               


                     Modifié par Rolo Kipp, 23 août 2011 - 08:02 .
                     
                  


            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
SummonPack v0.3 :-P
« Reply #5 on: August 23, 2011, 09:06:30 pm »


                rk_searcherspawn (pathfinding creature's OnSpawn)



/*  rk_searcherspawn
        v0.3
    by Rolo Kipp   */
void main()
{
  // Set up searcher to run
  location lStartLocation = GetLocation(OBJECT_SELF); // Store info to hand off to PackMember
  int nPackLevel = GetLocalInt(OBJECT_SELF,"nPackLevel");

  int nLifeTime = Random((nPackLevel*3))+ 3; // How long this searcher lives
  float fLifeTime = IntToFloat(nLifeTime);
  // Create the effect to apply
  effect eDeath = EffectDeath();

  // Apply the effect to the object
  DelayCommand(fLifeTime, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, OBJECT_SELF));
  // run away!
  ActionMoveAwayFromLocation(lStartLocation,TRUE,40.0f);
}


               
               

               


                     Modifié par Rolo Kipp, 23 août 2011 - 08:08 .
                     
                  


            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
SummonPack v0.3 :-P
« Reply #6 on: August 23, 2011, 09:08:26 pm »


               rk_searcherdeath (pathfinding creature's OnDeath)



/*  rk_searcherdeath
        v0.3
    by Rolo Kipp   */
void main()
{
  // create packmember and kill searcher
  location lSpawnIn = GetLocation( OBJECT_SELF ); // Where to spawn packmember
  string sPackType = GetLocalString(OBJECT_SELF,"sPackType"); //Packmember ResRef
  object oPackMember = CreateObject(OBJECT_TYPE_CREATURE, sPackType, lSpawnIn, FALSE);

  //summoned PackMember, now retrieve and set info
  object oEnemy = GetLocalObject(OBJECT_SELF,"oEnemy"); //Summoner's enemy
  location lTargetLoc = GetLocalLocation(OBJECT_SELF,"lTargetLoc"); // Enemy's old location
  SetLocalObject(oPackMember,"oEnemy",oEnemy);
  SetLocalLocation(oPackMember,"lTargetLoc",lTargetLoc);
}


               
               

               
            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
SummonPack v0.3 :-P
« Reply #7 on: August 23, 2011, 09:10:29 pm »


                rk_packspawn (packmember's OnSpawn)


/*  rk_packspawn
        v0.3
    by Rolo Kipp   */
void main()
{
  // Set up packmember
  object oEnemy = GetLocalObject(OBJECT_SELF,"oEnemy"); // Who is the enemy?
  location lTargetLoc = GetLocalLocation(OBJECT_SELF,"lTargetLoc"); // Fallback if oEnemy gone

  // Play summoning sound
  string sSummonResponse = GetLocalString(OBJECT_SELF,"sSummonResponse"); //Sound played when summoned
  PlaySound(GetLocalString(OBJECT_SELF,"sSummonResponse"));
  SpeakString("I'm coming!");
  //Level up to nPackLevel
  int nDidLevel = LevelUpHenchman( OBJECT_SELF, class_TYPE_INVALID, TRUE, PACKAGE_INVALID);
  // Debug SpeakString( IntToString( nDidLevel );
  // Note: Need to give level/class appropriate gear :-P

  // Move close and Attack enemy
  if (GetIsObjectValid(oEnemy) == FALSE) ActionMoveToLocation(lTargetLoc, TRUE);
  ActionMoveToObject(oEnemy, TRUE); //if enemy exists then run toward
}