Author Topic: PC penalty when swarmed by hostiles  (Read 379 times)

Legacy_Terrorble

  • Sr. Member
  • ****
  • Posts: 370
  • Karma: +0/-0
PC penalty when swarmed by hostiles
« on: November 22, 2013, 02:21:51 am »


               I'm toying with the idea of a dodge AC penalty to PCs that are being attacked by 4 or more NPCs. It would account for dwarven defender levels and involve a tumble check.  Problem is, I can't think of how or where best to check if the player is surrounded.
               
               

               
            

Legacy_Squatting Monk

  • Hero Member
  • *****
  • Posts: 776
  • Karma: +0/-0
PC penalty when swarmed by hostiles
« Reply #1 on: November 22, 2013, 02:43:58 am »


               The only thing I can think of is to put an AoE on the PC that increments a counter when hostiles enter and decrements it when they leave. If the counter rises to 4, apply your penalties.
               
               

               
            

Legacy_MagicalMaster

  • Hero Member
  • *****
  • Posts: 2712
  • Karma: +0/-0
PC penalty when swarmed by hostiles
« Reply #2 on: November 22, 2013, 03:06:17 am »


               Could just run it on the module heartbeat or a psuedo-heartbeat on the PC himself.  Check every X enemies to see how many enemies are within Y yards or whatever.
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
PC penalty when swarmed by hostiles
« Reply #3 on: November 22, 2013, 04:17:58 pm »


               AoEs are no good unless you're single player, and somewhat dodgy even then - we generally replace them with psuedos. The problem is, pseudos are about 5x the overhead of a comparable heartbeat, and you'd only want them running during combat.

I think my inclination would be to run it off the monsters themselves, either in heartbeat or from endcombat. You get a different issue there, though, in that every critter is firing that same code (it'd have to be on all critters, in the default ai or a hook from it). So, you're then in a situation where you'd need to mark each critter as counted for a particular PC - you'd probably want both a timestamp and a local object var, to limit how often it's recalculated.

Long story short, if this is for a single-player or few-player mod, your best bet is probably the module heartbeat, doing a GetFirstPlayer (or looping through all if MP) and checking how many creatures are within x radius of them.

If you're expecting more than a few pcs on at once, though, you're probably going to want to check from encombat or creature heartbeat, which will be both more efficient, and more difficult to code properly.

Two questions:
1) SP or MP?
2) Are you using NWNX? If so, windows or linux?


Funky
               
               

               


                     Modifié par FunkySwerve, 22 novembre 2013 - 04:20 .
                     
                  


            

Legacy_Terrorble

  • Sr. Member
  • ****
  • Posts: 370
  • Karma: +0/-0
PC penalty when swarmed by hostiles
« Reply #4 on: November 22, 2013, 05:52:39 pm »


               1. The module is setup for MP, but will unlikely see more than 3-4 players.
2. On Windows. No NWNX currently.

So, I've thrown this together on the module heartbeat.  I track heartbeats (which has worked reliably so far), and this should fire every 2nd one.  If it works, I'll give the numbers and the role of dwarven defender more thought later.

Of course, thanks for the replies.  Using an AoE didn't cross my mind.

if( nHB % 2 == 0 )

{

  while( GetIsObjectValid(oPC) )

  {

    if( GetIsInCombat(oPC) )

    {

      int iCount = 0;

      int n = 1;

      object oEnemy = GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,oPC,n);

      while( GetDistanceBetween(oPC,oEnemy) < 4.0 )

      {

        iCount++;

        n++;

      oEnemy = GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,oPC,n);

      }

      if( iCount > 3 )

      {

        int nOppRoll = 10 + (iCount-2)*5;//the DC is at least 20

        int nMyRoll  = d20() + GetSkillRank(SKILL_TUMBLE,oPC);

        if( nMyRoll < nOppRoll )

        {

            effect eSwarm = EffectACDecrease(iCount-2);//Minimum AC decrease of 2

            eSwarm = SupernaturalEffect(eSwarm);

            effect eVis = EffectVisualEffect(VFX_IMP_HEAD_EVIL);

            ApplyEffectToObject(DURATION_TYPE_INSTANT,eVis,oPC);

            ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eSwarm,oPC,12.0);


            FloatingTextStringOnCreature("You are swarmed and unable to maneuver well.",oPC,FALSE);

        }

      }

    }

  oPC = GetNextPC();

  }

}
               
               

               


                     Modifié par Terrorble, 23 novembre 2013 - 06:15 .
                     
                  


            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
PC penalty when swarmed by hostiles
« Reply #5 on: November 22, 2013, 09:36:03 pm »


               You are counting the number of objects (not necessarily enemies) within 4.0 meters.  It might be better to use your GetNearestCreature() function to simulate the loop by incrementing it until the creature reached is beyond 5.0 meters (or 4.0 meters not sure which one you are going for).
               
               

               
            

Legacy_Terrorble

  • Sr. Member
  • ****
  • Posts: 370
  • Karma: +0/-0
PC penalty when swarmed by hostiles
« Reply #6 on: November 23, 2013, 06:22:25 am »


               Thanks, WhiZard!  You just saved me some time.  I like the idea of using GetNearestCreature() instead of scanning objects in the shape.  Besides, it will check for hostiles without me having to do that in a separate step anyway (which I clearly forgot to do the first time around).  I edited the code above to reflect it.

Now, my hope is that some of my weaker NPCs (e.g. goblins, spiders) will be respected a little more for their numbers.
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
PC penalty when swarmed by hostiles
« Reply #7 on: November 24, 2013, 03:33:01 am »


               GNC with reaction check is how I would've done it, yeah. The question about NWNX is moot, I think. I was asking mainly because being able to assign and check effect ids and durations would have made the more complex method somewhat easier.

Funky
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
PC penalty when swarmed by hostiles
« Reply #8 on: November 24, 2013, 09:06:08 pm »


               

Terrorble wrote...


      int iCount = 0;

      int n = 1;

      object oEnemy = GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,oPC,n);

      while( GetDistanceBetween(oPC,oEnemy) < 4.0 )

      {

        iCount++;

        n++;

      oEnemy = GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,oPC,n);

      }

      if( iCount > 3 ) ...

      

 

I see no reason for a loop here.   all you need to do is find the 4th nearest enemy creature then find out if the is valid and check the distance.  

 
oEnemy = GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,oPC,4);

if ( oEnemy != OBJECT_INVALID && GetDistanceBetween(oPC,oEnemy) < 4.0 ) ...
               
               

               
            

Legacy_Terrorble

  • Sr. Member
  • ****
  • Posts: 370
  • Karma: +0/-0
PC penalty when swarmed by hostiles
« Reply #9 on: November 25, 2013, 06:36:17 am »


               I'm very glad I posted this question, instead of mulling through it myself.  Thanks for the insight.

There is one reason I may do the loop.  If the total number of enemies within 4.0m determines the DC of the tumble check and the severity of the penalty, then I need to know how many there are.  But even then, I think I could use this idea to optimize the loop, start at n = 4 and go up from there.