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.
PC penalty when swarmed by hostiles
Débuté par
Terrorble
, nov. 22 2013 02:21
#1
Posté 22 novembre 2013 - 02:21
#2
Posté 22 novembre 2013 - 02:43
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.
#3
Posté 22 novembre 2013 - 03:06
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.
#4
Posté 22 novembre 2013 - 04:17
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
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 .
#5
Posté 22 novembre 2013 - 05:52
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();
}
}
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 .
#6
Posté 22 novembre 2013 - 09:36
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).
#7
Posté 23 novembre 2013 - 06:22
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.
Now, my hope is that some of my weaker NPCs (e.g. goblins, spiders) will be respected a little more for their numbers.
#8
Posté 24 novembre 2013 - 03:33
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
Funky
#9
Posté 24 novembre 2013 - 09:06
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 ) ...
#10
Posté 25 novembre 2013 - 06:36
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.
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.





Retour en haut







