Author Topic: How DelayCommand() works in this case?  (Read 462 times)

Legacy_WhiteTiger

  • Hero Member
  • *****
  • Posts: 889
  • Karma: +0/-0
How DelayCommand() works in this case?
« on: June 05, 2015, 10:05:56 am »


               

Hello Scripters, 


 


I have just two question of this issue:


 


1) In this case, supposing that the integer variable "Aaaaa" could change because another event script, what happens in the check of the void "doCheck()"? The iCurrentVal variable will be different of the iInitialVal?


 


2) Do the loop here works fine? The object oAny will be unique because of the delay of 60 seconds or only one? What happens with the loop when we have delay inside?



void doCheck(object oPC, int iInitialVal)
{
   int iCurrentVal = GetLocalInt(oPC, "Aaaaa");
   if(iCurrentVal == iInitialVal)
   {
      // * The actions I want that must be added here.
   }
}

void main()
{
   object oAny = GetFirstPC();
   int iInitialVal;

   while(GetIsObjectValid(oAny))
   {
      SetLocalInt(oAny, "Aaaaa", Random(999999)+1);
      iInitialVal = GetLocalInt(oAny,"Aaaaa");
      DelayCommand(60.0, doCheck(oAny, iInitialVal));
      oAny = GetNextPC();
   }
}


               
               

               
            

Legacy_Tarot Redhand

  • Hero Member
  • *****
  • Posts: 4165
  • Karma: +0/-0
How DelayCommand() works in this case?
« Reply #1 on: June 05, 2015, 12:32:47 pm »


               

Before I answer your queries, you might like to consider this more efficient alternative version of your void main function.




void main()
{
    object oAny = GetFirstPC();
    int iInitialVal = Random(999999)+1;

    while(GetIsObjectValid(oAny))
    {
        SetLocalInt(oAny, "Aaaaa", iInitialVal);
        DelayCommand(60.0, doCheck(oAny, iInitialVal)); 
        iInitialVal = Random(999999)+1;
        oAny = GetNextPC();
    }
}

To answer your questions


 



  1. It depends on what the other event does to "Aaaaa". The function doCheck tests iInitialVal against iCurrentVal at the time that doCheck actually executes.

  2.    
  3. Yes the loop will work fine. oAny will be unique. The delay does not affect the loop, only when the function doCheck actually fires. One possible problem with your code as it stands is that oPC may have left the pw in that 1 minute delay. To prevent this you could use -


void doCheck(object oPC, int iInitialVal)
{
    if(!(GetIsPC(oPC)))
        return;    ...

One other thing. Studying either version of the lexicon can help when you have queries about such things as this.

 

TR


               
               

               
            

Legacy_MrZork

  • Hero Member
  • *****
  • Posts: 1643
  • Karma: +0/-0
How DelayCommand() works in this case?
« Reply #2 on: June 05, 2015, 04:37:16 pm »


               

What TR said, particularly that DoCheck should probably have a call to GetIsObjectValid(oPC).


 


I am curious what the purpose of the script is? Specifically, why the random number? It almost appears like an attempt to have something happen 1 in 999999 times unless some other script changes local in Aaaaa. But, it seems more likely that, whatever the random number is, unless something changes Aaaaa in the intervening seconds, the other actions in DoCheck always happen 60 seconds later, and they still rarely happen even if some other script has changed Aaaaa, unless that other script sets Aaaaa to something outside the range [1, 999999].



               
               

               
            

Legacy_WhiteTiger

  • Hero Member
  • *****
  • Posts: 889
  • Karma: +0/-0
How DelayCommand() works in this case?
« Reply #3 on: June 05, 2015, 07:00:35 pm »


               


What TR said, particularly that DoCheck should probably have a call to GetIsObjectValid(oPC).


 


I am curious what the purpose of the script is? Specifically, why the random number? It almost appears like an attempt to have something happen 1 in 999999 times unless some other script changes local in Aaaaa. But, it seems more likely that, whatever the random number is, unless something changes Aaaaa in the intervening seconds, the other actions in DoCheck always happen 60 seconds later, and they still rarely happen even if some other script has changed Aaaaa, unless that other script sets Aaaaa to something outside the range [1, 999999].




 


Sorry, I does not use GetFirstPC() and GetNextPC() in my original code. I use GetFirstObjectInArea() and GetNextObjectInArea(). This script fires ondamaged, so the 1/999.999 chance isn't for rarely happen, is for never happen.



               
               

               
            

Legacy_WhiteTiger

  • Hero Member
  • *****
  • Posts: 889
  • Karma: +0/-0
How DelayCommand() works in this case?
« Reply #4 on: June 05, 2015, 07:07:59 pm »


               

TR why you deleted it?

 



SetLocalInt(oAny, "Aaaaa", Random(999999)+1;
iInitialVal = GetLocalInt(oAny, "Aaaaa");

the Random() function has a bug when you use this directly has ever a different value according my experiences



               
               

               
            

Legacy_Tarot Redhand

  • Hero Member
  • *****
  • Posts: 4165
  • Karma: +0/-0
How DelayCommand() works in this case?
« Reply #5 on: June 05, 2015, 08:26:05 pm »


               
Yes Random has a bug. That bug means that you get the same sequence of numbers produced for any given area. It only affects mp/pw games when there is one and only one PC playing. The way that the start point in the list of numbers produced is by taking numeric bits from certain parts of an area. This information is in the lexicon. I double checked both versions of the lexicon to make sure. The method that you are using to try to get around this will not work according to the information in the lexicon (if it does work, get in touch with the people behind the lexicon so they can alter it). If you are worried about this bug put a call to this little function in your void main() before Random is called.



void PseudoRandomise()
{
    intMaxIteration = GetTimeMillisecond() + 100;
    int iIndex;
    int iDummy;


    for(iIndex = 0 ; iIndex < intMaxIteration ; iIndex++)
        iDummy = Random(iIndex + intMaxIteration);
)


In answer to your question as to why I changed it, I did so because my version is both more efficient and more elegant.

 

Now for the Really bad news. The only object that has a chance of doing the actions that you want in doCheck is the very last one found. There is a very remote chance that the other event script that you mention in your 1st question could alter the variable "Aaaaa" so that it matches a different object but the chances of this happening are vanishingly small.

 

The reason why is as follows. Each time through your while loop the value of "Aaaaa" is changed. All that the DelayCommand function does is to place the call to the delayed function on a list of functions that will be executed later. Once it has done that the next instruction in your loop is executed. As this happens very fast and you have a delay of 60 seconds the only value for "Aaaaa" your delayed function calls will all see is the very last one generated.

 

TR

               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
How DelayCommand() works in this case?
« Reply #6 on: June 05, 2015, 10:52:59 pm »


               


 


Yes Random has a bug. That bug means that you get the same sequence of numbers produced for any given area.

 




 


Do you have solid evidence of this?  I have seen the bug reported on many posts of the past, some with extensive calculations (which are now retracted) for determining exactly the seed, but when tested over the last five years, no one has been able to replicate these circumstances.  No matter where the random number is being calculated (client enter, module enter, area enter) there keeps on being a different seed value.


               
               

               
            

Legacy_Tarot Redhand

  • Hero Member
  • *****
  • Posts: 4165
  • Karma: +0/-0
How DelayCommand() works in this case?
« Reply #7 on: June 06, 2015, 12:03:08 am »


               

I have not done any testing on this. I rely on what's in the lexicon (both versions). TBH I wasn't even aware there might be a problem until WhiteTiger mentioned it. At that point I checked first the downloadable (and so much easier to search) lexicon 1.69. I then checked the online version to be sure there hadn't been any updates to that information. Not being as knowledgeable about NwN script as some people on here are, I rely on the lexicon and trust what is written therein. Assuming that it is correct I wrote that small PseudoRandomise routine which should go some way to mitigating any such bug as is reported in the lexicon.


 


TR



               
               

               
            

Legacy_Proleric

  • Hero Member
  • *****
  • Posts: 1750
  • Karma: +0/-0
How DelayCommand() works in this case?
« Reply #8 on: June 06, 2015, 06:45:17 am »


               The Lexicon is very reliable, but, like any wiki, there are occasional errors. If other people have verified this one, I'll change it.
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
How DelayCommand() works in this case?
« Reply #9 on: June 06, 2015, 04:22:13 pm »


               




The Lexicon is very reliable, but, like any wiki, there are occasional errors. If other people have verified this one, I'll change it.




 


There are a lot of old conversations to dig through, but if you want a completely independent source try this one.  Notice toward the bottom a second statistical tests was performed for the reseeding (which does not reseed to the same value).


               
               

               
            

Legacy_Proleric

  • Hero Member
  • *****
  • Posts: 1750
  • Karma: +0/-0
How DelayCommand() works in this case?
« Reply #10 on: June 06, 2015, 10:23:46 pm »


               I changed the wiki, leaving the alleged bug details on the discussion page, in case anyone wants to make a case for it.


Evidently, measurement shows no significant bias in the random numbers, which is consistant with Acaos's finding that the server timestamp is used to reseed the function.
               
               

               
            

Legacy_Tarot Redhand

  • Hero Member
  • *****
  • Posts: 4165
  • Karma: +0/-0
How DelayCommand() works in this case?
« Reply #11 on: June 07, 2015, 01:12:18 am »


               

Which is all fine and dandy for pw's but what about sp mods? Do the claims that were on the lexicon hold or not in that case?


 


TR



               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
How DelayCommand() works in this case?
« Reply #12 on: June 07, 2015, 02:28:25 am »


               


Which is all fine and dandy for pw's but what about sp mods? Do the claims that were on the lexicon hold or not in that case?


 


TR




 


The claims do not hold at all for SP mods.  Random() does not just reset to the same seed.


               
               

               
            

Legacy_Proleric

  • Hero Member
  • *****
  • Posts: 1750
  • Karma: +0/-0
How DelayCommand() works in this case?
« Reply #13 on: June 07, 2015, 08:57:04 am »


               Since the engine seeds from the timestamp, you'd expect SP to be equally random. My latest SP module does a bunch of random stuff on first area entry, which turns out different every time, so it's good enough, for practical purposes.
               
               

               
            

Legacy_Tarot Redhand

  • Hero Member
  • *****
  • Posts: 4165
  • Karma: +0/-0
How DelayCommand() works in this case?
« Reply #14 on: June 07, 2015, 10:09:12 am »


               

I am glad we have apparently cleared that up. Is it possible that this bug existed in previous versions of NwN but was fixed in a more modern (i.e. 1.65, 1.67, whatever) and we just weren't told?


 


TR