Author Topic: While Loop causing TMI explosions!?!? *Fireworks*  (Read 419 times)

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
While Loop causing TMI explosions!?!? *Fireworks*
« on: February 05, 2013, 07:16:34 pm »


               

void main()
  {
object oPlayer = GetLastPlayerDying();
location lPlayerDying = GetLocation(oPlayer);
object oHostile = GetFirstObjectInShape(SHAPE_SPHERE, 17.0, lPlayerDying, TRUE, OBJECT_TYPE_CREATURE);

 while (GetIsObjectValid(oHostile))
  {
   if (GetIsReactionTypeHostile(oHostile, oPlayer)) //Checks for hostiles, if none, player heals
    {
    DelayCommand(6.0, ExecuteScript("ens_dyingcheck", oPlayer));
    }
   oHostile = GetNextObjectInShape(SHAPE_SPHERE, 17.0, lPlayerDying, TRUE, OBJECT_TYPE_CREATURE);
  }

 }


This is an attempt at making a pseudoheartbeat. I saw a post from Shado0o0W suggesting using the execute script method, so I followed the suggestion and saw a slight increase in the time before NWN goes into a 'hang'. It's being called from here:

//Check to see if Henchmen are still alive
if (GetCurrentHitPoints(oHench1) <= 0 && GetCurrentHitPoints(oHench2) <= 0)
 {//If not, remove immortality and initiate player death
 SetPlotFlag(oPlayer, FALSE);
 ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, oPlayer);
 }
//If alive, check to see if hostiles are present within 17 meters
else if (GetCurrentHitPoints(oHench1) >= 1 || GetCurrentHitPoints(oHench2) >= 1)
 {
 ExecuteScript("ens_dyingcheck", oPlayer); //Runs a check to see if hostiles are present
 }


Is there an alternative method I am missing here?
               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
While Loop causing TMI explosions!?!? *Fireworks*
« Reply #1 on: February 05, 2013, 09:52:16 pm »


               Digging through old, old, old threads, I found a suggestion about calling PC's directly from the Playerlist using GetFirstPC();, which means heartbeat would only be running in the area the PC is in.

Thus was born this:

/////////////////Death System, NineCoronas////////////
void main()
{
object oPC = GetFirstPC();
object oHench1 = GetHenchman(oPC, 1);
object oHench2 = GetHenchman(oPC, 2);
location lPCDying = GetLocation(oPC);
effect eDeath = EffectDeath(FALSE, FALSE);

//Check for dying variable on PC
if(GetLocalInt(oPC, "PlayerDying"))
{
 //Check to see if Henchmen are still alive
 if (GetCurrentHitPoints(oHench1) <= 0 && GetCurrentHitPoints(oHench2) <= 0)
 {//If not, remove plot status, kill player, and delete Dying integer
 SetPlotFlag(oPC, FALSE);
 ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, oPC);
 DeleteLocalInt(oPC, "PlayerDying");
 }
 //If Hench are alive, check to see if hostiles are present within 17 meters
 else if (GetCurrentHitPoints(oHench1) >= 1 || GetCurrentHitPoints(oHench2) >= 1)
 {
 FloatingTextStringOnCreature("Found henchman with more than 1 HP", oPC);
 object oHostile = GetFirstObjectInShape(SHAPE_SPHERE, 17.0, lPCDying, TRUE, OBJECT_TYPE_CREATURE);
  while (GetIsObjectValid(oHostile))
   {
   FloatingTextStringOnCreature("Found " + GetName(oHostile), oPC);
   if (GetIsReactionTypeHostile(oHostile, oPC))
    {
    FloatingTextStringOnCreature("Hostile Creature Check Is also Working!", oPC);
    return; //If a hostile creature is found, do nothing? Heartbeat will check again soon. While will run through all objects until it either finds no hostiles or finds one. Finding one will break this routine.
    }
   oHostile = GetNextObjectInShape(SHAPE_SPHERE, 17.0, lPCDying, TRUE, OBJECT_TYPE_CREATURE); //Check next object to see if hostile
   }
 DeleteLocalInt(oPC, "PlayerDying"); //Delete Dying Int
 ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(15), oPC); //Heal PC
 FloatingTextStringOnCreature("Your companions rouse you from unconsciousness...", oPC);//Send RP message
 }
}
}


Which appears to working like a charm. '<img'>
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
While Loop causing TMI explosions!?!? *Fireworks*
« Reply #2 on: February 05, 2013, 09:54:09 pm »


               the executed script and its instructions still counts towards the current handling

to avoid that the executescript or custom function doing the rest of the script must be delayed by some ammount of time

but thats only a general answer, it still might be problem in your script or way how you are trying to solve your problem
               
               

               


                     Modifié par ShaDoOoW, 05 février 2013 - 09:56 .
                     
                  


            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
While Loop causing TMI explosions!?!? *Fireworks*
« Reply #3 on: February 05, 2013, 09:54:28 pm »


               you should ensure that this is single player.

let the player know that the module needs to be single player, and you should be fine.
               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
While Loop causing TMI explosions!?!? *Fireworks*
« Reply #4 on: February 05, 2013, 10:00:43 pm »


               

ShaDoOoW wrote...

the executed script and its instructions still counts towards the current handling

to avoid that the executescript or custom function doing the rest of the script must be delayed by some ammount of time

but thats only a general answer, it still might be problem in your script or way how you are trying to solve your problem


I'm not sure what it was, but NWN was essentially locking up (music would still play). In the heartbeat version, it was doing it as well until I removed the While Loop I had wrapped in a custom function designed to clean up blood placeables. I just ended up trashing the wrapper and adding a destroy object into the functions that created the placeables in the first place.

Actually, Shado0ow, you're the one who inspired using this method in that aforementioned old, old, old thread, so... thanks.

@ Henesua: I'll be sure too. '<img'>

Now to get this working for henchman...

Cheers!

-NineCoronas
               
               

               
            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
While Loop causing TMI explosions!?!? *Fireworks*
« Reply #5 on: February 05, 2013, 10:27:41 pm »


               <puzzling...>

NineCoronas2021 wrote...

void main()
 
 while (GetIsObjectValid(oHostile))
  {
   if (GetIsReactionTypeHostile(oHostile, oPlayer)) //Checks for hostiles, if none, player heals
    {
    DelayCommand(6.0, ExecuteScript("ens_dyingcheck", oPlayer));
    }
   oHostile = GetNextObjectInShape(SHAPE_SPHERE, 17.0, lPlayerDying, TRUE, OBJECT_TYPE_CREATURE);
  }

This checks for hostiles-> if found, has player call itself (ens_dyingcheck) in 6 seconds, correct?

//Check to see if Henchmen are still alive
if (GetCurrentHitPoints(oHench1) <= 0 && GetCurrentHitPoints(oHench2) <= 0)
 {//If not, remove immortality and initiate player death
 SetPlotFlag(oPlayer, FALSE);
 ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, oPlayer);
 }
//If alive, check to see if hostiles are present within 17 meters
else if (GetCurrentHitPoints(oHench1) >= 1 || GetCurrentHitPoints(oHench2) >= 1)

You've already checked that *at least one henchman* is alive in the first "if", yes?
So this should just be "else" statement.

 {
 ExecuteScript("ens_dyingcheck", oPlayer); //Runs a check to see if hostiles are present
 }

What is *this* script fired by? 

<...even people who know him>
               
               

               
            

Legacy_JediMindTrix

  • Sr. Member
  • ****
  • Posts: 383
  • Karma: +0/-0
While Loop causing TMI explosions!?!? *Fireworks*
« Reply #6 on: February 06, 2013, 12:18:26 am »


               The first if checks to see if any are dead, the second one checks for life, hence 'else if henchman are alive...'

That execute script is erroneous and no longer used. Once I completely finish the death system I'll post a 'final' version.
               
               

               
            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
While Loop causing TMI explosions!?!? *Fireworks*
« Reply #7 on: February 06, 2013, 12:31:49 am »


               <sharpening...>

That was my point.
if (GetCurrentHitPoints(oHench1) <= 0 && GetCurrentHitPoints(oHench2) <= 0)
...returns true only if *both* henchmen are dead. So if it returns false (reaches the "else" statement) then at least one henchman is alive.

<...a stake>
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
While Loop causing TMI explosions!?!? *Fireworks*
« Reply #8 on: February 06, 2013, 01:34:07 am »


               

NineCoronas2021 wrote...

Actually, Shado0ow, you're the one who inspired using this method in that aforementioned old, old, old thread, so... thanks.

I know, but if you are talking about *that* post, then this was meant for different purposes than yours - for cases such as loop inside loop hitting TMI limit. AND also, later I found it needless. It works, but make a new script for that is needless since you can achieve same results with a function. In that regard I found my old solution overcome and cannot recommend anymore.
               
               

               
            

Baaleos

  • Administrator
  • Hero Member
  • *****
  • Posts: 1916
  • Karma: +0/-0
While Loop causing TMI explosions!?!? *Fireworks*
« Reply #9 on: February 06, 2013, 10:02:21 am »


               

while (GetIsObjectValid(oHostile))
 {
  if (GetIsReactionTypeHostile(oHostile, oPlayer)) //Checks for hostiles, if none, player heals
   {
   DelayCommand(6.0, ExecuteScript("ens_dyingcheck", oPlayer));
   }
  oHostile = GetNextObjectInShape(SHAPE_SPHERE, 17.0, lPlayerDying, TRUE, OBJECT_TYPE_CREATURE);
 }

It should also be noted that - while yes - this loop does delay execute of the script to be 6 seconds after the fact.
It doesnt however consider that all of those delayed scripts will be going off at the same time.

I believe in a post on the old forums Funkyswerve said something like there was a 128k limit on data that can pass through a script at a single time.

An example where I saw this -  was when some of my AI Scripts in my module, would throw TMI's if there were large scale battles.
But they wouldnt throw TMI's if the creature count in the battle was less than 5.
EG- Each creature is firing the same small script, but the multiplication per creature, made it so if they were all firing at same time- it throws TMI.

If you really want to get around TMI in that loop, you should try to implement a multiplier in your loop.


int i = 1;
while (GetIsObjectValid(oHostile))
  {
   if (GetIsReactionTypeHostile(oHostile, oPlayer)) //Checks for hostiles, if none, player heals
    {
    DelayCommand(6.0+IntToFloat(i), ExecuteScript("ens_dyingcheck", oPlayer));
    }
   oHostile = GetNextObjectInShape(SHAPE_SPHERE, 17.0, lPlayerDying, TRUE, OBJECT_TYPE_CREATURE);
i++;
  }


This way - your individual scripts are given a 1 second of dedicated time to execute, before the next one kicks off.