What's the point?
#26
Posté 07 février 2013 - 06:40
#27
Posté 07 février 2013 - 07:01
It doesn't really matter, because you shouldn't create scripts that would cause
a TMI with either maximum setting, both will freeze the game for a visible
amount of time [/icon_smile.gif]
_________________
georg zoeller
senior
rules and systems monkey
[da | me]
My custom NWN
content
ceterum censeo ambulatiuncula esse delen
If that were still true, we wouldn't be getting away with our 8M limit.
Here's another one that's tangentially relevant:
And one more:Makazasky
It seem to be a must to use Jasperre AI... but server
that i know that are using it keep getting TMI error... so i guess it also cause
lag, and the creature, even if they act more originally... dont seem to be more
smart
So ... considering im building a server not very focus on PvM... should
still use Jasperre AI?
FunkySwerve
We removed it after about a two years as it was just
too cumbersome with all the looping, and because we found the beholder ai (with
maxed magic int) to be more deadly in most cases. Jasperre's is still nice for
casters, but in the end we decided it just wasn't worth the
overhead.
Funky
_________________
Higher Ground
Higher
Ground Legendary Level System for levels 41-60
Author
Message
DM_Spike
I have Jasperres AI scripts and have recently started
getting script errors in the window on the right.
They start with Too Many
Instrustions errors and are all creature script errors. They are random
creatures and nothing seems to trigger them.
It seems resetting the server
will settle them for a while, but there has been occasions when resetting from
inside the module, not hard resetting, makes them worse. Once they just scrolled
continuously, making the server unplayable.
Here is a link to the
screenshot.
Click
Here
666_SCARFACE_666
Same thing happens on my server from time to time, I
guess its to do with preformance after the server has been running for some
time.
_________________
Chaotic World Forums
Scarface's
Socketed Items V1.6
FunkySwerve
I've noticed the same phenomenon. It's seems to occur
most often on a few creatures, and I've been trying to deduce causes. On some
meleers it happens when their path to enemies is blocked (onblocked), but I've
seen a bunch of others that I cant yet explain, including some onperceived
wierdness from casters and meleers. What I've been wondering, but haven't had
time to check yet, is whether I have the same version of j_ai on all scripts.
The main version I use is 1.3, but I've seen a few that look different in
structure, enough so that they coul;d be an earlier version, and I could see
that playing havoc with includes etc. If you've had more than 1 version it might
be worth checking.
Best,
Funky
_________________
Higher Ground
Higher
Ground Legendary Level System for levels 41-60
Sorry, I couldn't find one of a dev explaining serial execution, though I did have a nice-if-overly-long trip down memory lane.
If you don't want to take my word for it, ask vman or anothe NWNX dev.
Funky
Modifié par FunkySwerve, 07 février 2013 - 07:05 .
#28
Posté 07 février 2013 - 07:09
That's another vman question. All I know is it falls under the same TMI limit as the calling script, so it's not really an exception as you say - the entire other script is executed, and then returns to the calling script. That's actually a pretty easy way to demonstrate serial execution (completion of ES before original continues), though it doesn't prove what the OP wants proved, since it could just be a behavior specific to ES.Squatting Monk wrote...
Please correct me if I'm wrong, Funky, but the exception to scripts running in parallel is when you call ExecuteScript(). The newly executed script gets run in the same timeslice and thus increases the instruction load on the parent script. Even then, this really isn't an exception to the rule, since the parent script is paused until the child finishes executing.
Put another way, the scripts still execute serially rather than simultaneously, but more technical than that I can't get, sorry.
Funky
#29
Posté 07 février 2013 - 07:15
Squatting Monk wrote...
Please correct me if I'm wrong, Funky, but the exception to scripts running in parallel is when you call ExecuteScript(). The newly executed script gets run in the same timeslice and thus increases the instruction load on the parent script. Even then, this really isn't an exception to the rule, since the parent script is paused until the child finishes executing.
You are correct. As far as instruction count goes ExecuteScript() is the same as calling any other function within the script. It executes the script and then returns to the calling script without reseting the instruction count.
EDIT: this is not really running in parallel, It just runs the script as a subrutine, Using the same VM-stack that was being used by the calling script. hence the reason the instruction count never gets cleared. When a script is delayed a new VM-stack is created for the running of the script, clearing the instruction count back to 0.
Modifié par Lightfoot8, 07 février 2013 - 10:16 .
#30
Posté 07 février 2013 - 07:17
Modifié par ffbj, 07 février 2013 - 07:28 .
#31
Posté 07 février 2013 - 07:27
I stopped reading at the first potential problem point, because the lack of indents was driving me nuts. This:ffbj wrote...
Np, and thanks for the definition. I wonder why sometimes I get a script that will TMI, it's a spawn script, but not always. I'd say about 1 out of 5 times it fires it TMI's. Well here it is:
object oPChp = GetFirstPC();
while (GetIsObjectValid(oPChp)||(oArea == GetArea(oPChp))){
if (oArea != GetArea(oPChp)){
oPChp = GetNextPC();
}
iHd++;
iHd += GetHitDice(oPChp); //trying to add the pc's in the area hp
oPChp = GetNextPC();
}
Looks suspect to me, because you iterate oPChp twice in some loops. I can't guaranteed it's the cause, as I haven't tested, but I would write this as a for loop instead, to make use of continue.
for (oPChp = GetFirstPC(); GetIsObjectValid(oPChp); oPChp = GetNextPC()) {
if (oArea != GetArea(oPChp))
continue;
iHd++;
iHd += GetHitDice(oPChp); //trying to add the pc's in the area hp
}
If you're using the default compiler, however, I don't think it'll let you, so you woud instead use:
object oPChp = GetFirstPC();
while (GetIsObjectValid(oPChp)||(oArea == GetArea(oPChp))){
if (oArea != GetArea(oPChp)){
oPChp = GetNextPC();
} else {
iHd++;
iHd += GetHitDice(oPChp); //trying to add the pc's in the area hp
oPChp = GetNextPC();
}
}
If, in fact, that's the functionality you intended.If you indent the rest properly I'll be happy to take a look at the rest and find the problem, if the above isn't it.
Funky
#32
Posté 07 février 2013 - 07:52
I was about to comment on the loop too but for different reasons. That logical OR in the loop
condition looks suspect to me. I think you mean it to be AND.
If for some reason oArea was invalid what you have is an infinite loop as soon as oPChp goes
invalid.
Cheers,
Meaglyn
#33
Posté 07 février 2013 - 08:15
Funky
#34
Posté 07 février 2013 - 08:46
AssignCommand, DelayCommand, etc all create new 'run script' events that are added to the server's event queue and so they get executed on their own, at recursion level zero if that makes sense.
NWN server is definitely single-threaded nothing can run in paralell.
Modifié par pope_leo, 07 février 2013 - 08:48 .
#35
Posté 07 février 2013 - 08:46
I've created 2 engines in my programming classes, it was me and 3 others. I know -exactly- how my particular part of the engine works, but how they did their parts... Not so much. I wasn't particularly eager to commit it all to memory. Georg likely knows a lot, but some of it he probably only has a jist of the idea. I'm doubtful even he knows many of the things we've learned over time. For instance that icons can be hidden using a method you've prescribed, that small size creatures can equip large sized weapons by changing appearance from medium to small, or my personal favorite, that people can produce weird little centaur like things as a result of horse glitches with appearance.(you really wouldn't expect it since horses are THEMSELVES nothing but a part based appearance of the normal one...)
However other then my little quip, I found out that this is indeed the case
I performed a test to timestamp each triggered script which explained it does infact trigger at different times.(though you can only tell with TONS of scripts set to fire at the same time as the computer is likely performing them in microseconds and timestamp doesn't record that far).
#36
Posté 07 février 2013 - 10:23
pope_leo wrote...
From what I remember the virtual machine has a recursion level that is incremented when you call ExecuteScript. If you called more than 7 nested ExecuteScripts it would error out. All these share the same TMI counter.
AssignCommand, DelayCommand, etc all create new 'run script' events that are added to the server's event queue and so they get executed on their own, at recursion level zero if that makes sense.
NWN server is definitely single-threaded nothing can run in paralell.
The recursion level level is 0x100 or 256, It applies to all recersive function calls not just scripts. Extending it is a little more difficult then increasing the instruction count counter because its limit is based on the size of the buffer originally allocated for the storage of the return pointers.
#37
Posté 07 février 2013 - 10:46
Highv Priest wrote...
Lightfoot8 wrote...
Highv Priest wrote...
It doesn't transfer ownership(at least for effects which are the only things that have "GetCreator" anyway). For instance if you use executescript on a PC from a module event. The effect applied is applied under the module and not the PC. The executescript as far as I can tell only sets the OBJECT_SELF to be the thing it's running on, but doesn't flag it as the owner of the script being run.
It does transfer ownership, Even for effects. If from a module event you execute a script on the PC and the script that is now running on the PC creates an effect, the PC will be the creator not the module.
You must forgive me if I sound arrogant, but I know for certain that executescript does not change "GetEffectCreator" which is how I determine "ownership" of the script. Example =
if(GetLevelByclass(class_TYPE_ASSASSIN, oPC) >= 3)
{
ExecuteScript("bloodoath", oPC);
}
This script is applied both onrest and when weapons are unequipped, because we give an AC bonus for dual weilding and using large weapons(not that uncommonly). Assassins on our server receive an AC bonus relative to int mod(learned observation of combat methods and effective ability to deflect oncoming attacks based on perceived patterns is the explanation as to why they are given an AC bonus) Both events are module defined. On the weapon unequip this check is put to remove the AC bonus for weapons being removed:
while(GetIsEffectValid(eRemove))
{
if(GetEffectSubType(eRemove) == SUBTYPE_EXTRAORDINARY)
{
if(GetEffectType(eRemove) == EFFECT_TYPE_AC_INCREASE)
{
if(GetEffectDurationType(eRemove) == DURATION_TYPE_PERMANENT)
{
if(GetEffectCreator(eRemove) == oSelf) oSelf is the module here.
{
RemoveEffect(oPC,eRemove);
}
}
}
}
eRemove = GetNextEffect(oPC);
}
Now as you saw the executescript is being applied to the PC, which SHOULD transfer ownership of the effect to the PC, because the PC is defining, creating, and applying the effect. However it -doesn't-, the module is still considered the creator of the effect and between being stuck in exams and other problems I just decided to reapply the effect after weapon removal instead of figuring out what fool-proof method DOES transfer ownership. Although according to nwnlexicon(which is usually a pretty good resource) assigning an inner-include block of code with assigncommand does this, I couldn't be arsed to take the time testing it to find out until I get these real life problems out of the way.
Well it does not matter if you sound arrogant or not. Execute script does transferr the ownership.
As for your argument I only see the script getting ran on an object pointed to by the var oPC, I have now way to comfirm that it is a PC. There is really not enough of the application of the effect for me to tell who is applying it or how it is applyed.
To show that ownership does transfer I wrote two simple script. The first I placed in the OnEnter event for the first area. It is:
void main()
{
object oObj = GetFirstObjectInArea(OBJECT_SELF);
while (GetIsObjectValid(oObj))
{
ExecuteScript("effect",oObj);
oObj = GetNextObjectInArea(OBJECT_SELF);
}
}
The effect script that it runs on every object in the area is:
void main()
{
effect test = EffectCurse();
string Creator = ObjectToString(GetEffectCreator(test));
SendMessageToPC(GetFirstPC(),"Creator ="+Creator);
}
The output was as follows.
[CHAT WINDOW TEXT] [Thu Feb 07 17:32:51] Creator =d
[CHAT WINDOW TEXT] [Thu Feb 07 17:32:51] Creator =a
[CHAT WINDOW TEXT] [Thu Feb 07 17:32:51] Creator =4
[CHAT WINDOW TEXT] [Thu Feb 07 17:32:51] Creator =3
[CHAT WINDOW TEXT] [Thu Feb 07 17:32:51] Creator =b
[CHAT WINDOW TEXT] [Thu Feb 07 17:32:51] Creator =7
[CHAT WINDOW TEXT] [Thu Feb 07 17:32:51] Creator =2
[CHAT WINDOW TEXT] [Thu Feb 07 17:32:51] Creator =7ffffffe
[CHAT WINDOW TEXT] [Thu Feb 07 17:32:51] Creator =c
[CHAT WINDOW TEXT] [Thu Feb 07 17:32:51] Creator =6
[CHAT WINDOW TEXT] [Thu Feb 07 17:32:51] Creator =8
[CHAT WINDOW TEXT] [Thu Feb 07 17:32:51] Creator =9
[CHAT WINDOW TEXT] [Thu Feb 07 17:32:51] Creator =5
As you can see every effect was created by a differant object.
I am not shure what is causing the problem in your script. I can only tell you that it is not a problem with executeScript not changing ownership.
Modifié par Lightfoot8, 07 février 2013 - 10:48 .
#38
Posté 07 février 2013 - 11:26
Sorry to semi-highjack the thread.
Oh thought of a reaper strolling into town and everything, animals, people, etc.. would die/or save vrs.effect death, as the reaper approached them. Spawned from Lightfoots effect idea.
Something like that has been done too death, (sorry), I suppose like the plague in WarCraft. When all these PC's where just dropping over falling from the skies etc...That was amusing. Of course probably not to those to whom it happened.
Btw he did say it the script ran on unequiped and rest so it's just missing that those definitions. I think we can then assume that oPC refers to a PC.
Modifié par ffbj, 08 février 2013 - 12:26 .
#39
Posté 08 février 2013 - 01:10
As I said before and even few day ago to another guy. ExecuteScript shares the same code block and instruction limit. Thus you will notavoid TMI by this approach, to do that you would have to use some delay.Highv Priest wrote...
My idea is to have 5-10 scripts that simply have ExecuteScript("highv_smart_ai", OBJECT_SELF). Yes I'm extremely vain and I put highv in the name of all my original scripts >.>. Although highv_smart_ai is being executed, it's being done so under the code block of "smart_ai_1".
My idea is to have "smart_ai_1", "smart_ai_2", "smart_ai_3", etc. All of these essentially running "highv_smart_ai" in an attempt to circumvent the TMI error being triggered from many AI triggering the same script.
Anyway, using executescript function for AI is definitely good idea from customization reasons. The AI is called in several scripts and everytime someone wants to commit a change inside AI he have to rewrite all those scripts. If the AI was handled as a ExecuteScript, this problem would be eliminated entirely. But only one script is enough actually at the begining of the DetermineCombatRound. I wonder why I didnt thought about this, would be perfect feature for my community patch as Ive done many changes into the default AI.
This is wrong. Scripts are executed instantly and the original script waits for them to being finished.Highv Priest wrote...
Is there a way I could determine
whether or not nwn is capable of executing scripts at the same time?
This is hard to believe. Can you prove it? Sorry but Im not willing to test it myself, according that everything you've written so far turned to be incorrect and that you are base your knowledge on the results without debugging what cause that.So if nwn doesn't execute scripts at
the same time, why would 40 very simple heartbeats cause massive lag
when 40 very slightly differently timed heartbeats would not.(the delay
was between .01 to .40 based on their objecttostring ID in relation to
the first).
I can tell you for sure that if you spawn 50npcs at once, your heartbeat lag does not happen. Adding one or two lines of code, assuming this is not endless loop, cannot change this. BUT cast a fireball into this group of NPCs and your server might hang out for hours (at least on linux) due to the "cross-shout" issue I described in the threat about AI somewhere.
Modifié par ShaDoOoW, 08 février 2013 - 01:12 .
#40
Posté 08 février 2013 - 01:54
This isnt actually far off from what I have heard said on the legacy forums and from personal experience.So if nwn doesn't execute scripts at
the same time, why would 40 very simple heartbeats cause massive lag
when 40 very slightly differently timed heartbeats would not.(the delay
was between .01 to .40 based on their objecttostring ID in relation to
the first).
I've seen first hand that if you have for instance an AI Script - which is say - 400 lines long - or something like that
And then 5 NPC's start fighting - thats in effect 5x AI Scripts being triggered in combat state at sorta the same time.
Granted - the engine is single threaded, so each one has to finish its execution before the next one finishes.
But I remember once - I had some monsters that cast Summon Creature X or something like that, which caused my encounter of 5-6 monsters to become 12 - and then suddenly TMI frenzi.
The AI Script didnt suddenly become larger, it was just that there was more calls being made to the same script by more NPC's.
More memory/data was trying to be passed through the one script than the engine allowed.
I suppose technically - it might have allowed it to work - if half the mobs had 1 script being used for AI and the others had a differently named script being used.
Someone posted on the forums years ago explaining that the engine has a memory bandwidth limit of sorts -
That a certain amount of KB of data can only pass through a script at any one time - even if it is separate calls to that script.
I wont lie and say I understand it fully myself - but I have found that good ways to get away from the TMI error is to span the execution of large quantities of scripts with an incrementing integer changed to a float.
eg
Opposed to this - which might cause TMI in a vanilla setupfor(int i =1;i<=5000;i++)
{
DelayCommand(IntToFloat(i)*0.05,ExecuteScript("BLAHBLAH"));
}
for(int i =1;i<=5000;i++)
{
ExecuteScript("BLAHBLAH");
}
They are both doing sorta the same thing - except one is giving a second of dedicated execution time to the previous iteration of the script.
I will say that for this principal to actually work and be of use - the Script that is being executed, but be of significant size for this to provide any use.
Eg: If your script is tiny, and does execute and finish within a matter of miliseconds - then this wont provide benefit.
#41
Posté 08 février 2013 - 02:57
executecommand is instruction (or rather more than one instruction) that itself count to the TMI limit, with 5000iterations you would reach tmi with almost anything else
since nwn is single-threated, it means that no script can run at the same time (mean executed by game engine not within another script)
Modifié par ShaDoOoW, 08 février 2013 - 03:11 .
#42
Posté 08 février 2013 - 03:20
Modifié par Squatting Monk, 08 février 2013 - 03:20 .
#43
Posté 08 février 2013 - 07:47
Lightfoot8 wrote...
The recursion level level is 0x100 or 256, It applies to all recersive function calls not just scripts. Extending it is a little more difficult then increasing the instruction count counter because its limit is based on the size of the buffer originally allocated for the storage of the return pointers.
I went back and double checked... there is a separate script execution recursion level that has a hard coded limit of 8.
Script a:
void main()
{
object mod = GetModule();
int recurse_lvl = GetLocalInt(mod, "RECURSION_LEVEL");
SpeakString("Recursion Level: " + IntToString(recurse_lvl), TALKVOLUME_SHOUT);
SetLocalInt(mod, "RECURSION_LEVEL", ++recurse_lvl);
ExecuteScript("b", mod);
}
Script b:
void main()
{
object mod = GetModule();
int recurse_lvl = GetLocalInt(mod, "RECURSION_LEVEL");
SpeakString("Recursion Level: " + IntToString(recurse_lvl), TALKVOLUME_SHOUT);
SetLocalInt(mod, "RECURSION_LEVEL", ++recurse_lvl);
ExecuteScript("a", mod);
}
The final print would be "Recursion Level: 7". There will be no feedback if it throws an error.
Modifié par pope_leo, 08 février 2013 - 07:48 .
#44
Posté 08 février 2013 - 08:42
I beg your WHAT? You expect us to take you on your word based on some ai work and some programming classes, and get testy when I don't, but then refuse to accept the HotU project lead as an authority? The only salient difference I can see between the two appeals to authority is that I've never known HIM to be wrong. Oh, that, and a metric crapton more experience with all things NWN. Give me a break with this stuff, already.Highv Priest wrote...
Georg Zoeller said a lot of things >.>
Funky
Modifié par FunkySwerve, 08 février 2013 - 08:43 .
#45
Posté 08 février 2013 - 10:06
My testing is indeed flawed in many ways. However I can assure you that the 40 heartbeats were not utilizing enough code to adequately cause lag on their own. It's quite literally only composed of 3 commands(the spawns have true seeing so no check of visibility was necessary). GetAttackTarget, ActionAttack, and GetNearestCreature. The GetNearestCreature is only defined once GetAttackTarget returns object invalid(and it's very rare they will have no attack target).
As for Lightfoot I actually have gained respect for you. I found the problem was non-existent. Evidently originally that while loop must of not have contained a check for GetEffectCreator. Apparently some time in the past I fixed this check, but not until after I had come to the conclusion that executescript was faulty. So in an ironic twist I had fixed the problem without realizing what the problem was.(most likely during my reorganizing days where I recompile inefficient scripts into better versions).
I appreciate you taking the time to prove me wrong, giving me the ambition to re-assess the original proof that had originally driven me to that conclusion.
#46
Posté 08 février 2013 - 10:41
I know what you mean about those silent shouts: shouting I was attacked to everyone in the same faction. Thus all hostile if you have a PW with a couple hundred members belonging to hostile faction. What a drag. Of course Nwn was not designed for PW, and that was pointed out ad nauseum everytime someone would question something like that. Got rid of that stuff long ago. Mostly I just use perception and hardly any of my npc's have hb's.
Anyway not to knock the game. Since the difference between early Nwn and the final patch and later even with Shadoow's 1.70 and others work, for instance, made it so much better. Purely from scripting functionality with the addition of many new functions. Not to mention all the great haks and such, and custom content. Really what I am trying to get at is that it is a much superior game. (Preaching to the Choir)!
I tip my cap to all.
Modifié par ffbj, 08 février 2013 - 10:52 .
#47
Posté 08 février 2013 - 10:42
If you want to get to the bottom of the 40 heartbeat mystery, post the code and we can have at it. I'll admit it's hard to make sense of, the way you described it.
Funky
#48
Posté 08 février 2013 - 10:44
ffbj wrote...
Shadoow: Yes but isn't DCR called in different places?
I know what you mean about those silent shouts: shouting I was attacked to everyone in the same faction. Thus all hostile if you have a PW with a couple hundred members belonging to hostile faction. What a drag. Of course Nwn was not designed for PW, and that was pointed out ad nauseum everytime someone would question something like that. Got rid of that stuff long ago. Mostly I just use perception and hardly any of my npc's have hb's.
This is actually one of the reasons that the first suggestion in my delagging tutorial is custom factions. They help even if you've pared out a lot of the excess silent shouting in your ai, as we have.
Funky
#49
Posté 08 février 2013 - 10:52
(spoken on the side of the conversation)
responding to shouts and heartbeats are very useful in AI. In order to reduce their overhead, I do my best to only spawn NPCs when players are able to interact with them. And then I try to get rid of the NPCs as soon as they are unneeded.
#50
Posté 08 février 2013 - 11:07
I think one thing I did was limit the call to a range, because isn't the normal call server wide?
Of course if you have most of your monsters despawning that would not be a problem. Mostly I think lag is incurred with spawning and I have pretty much effectively reduced that cause of lag. For color I usually have things like animals on the perception diet, and then Pc's go away the animal just goes dormant, as you get a bit of lag from destroying/despawning. Still I am no lag expert as a friend says to me..Well you could never run a dozen people in your world cause it would lag out. Mostly related to, imo complex hb pc related and monster and active npc ai of specialized npc's: bounties, masterscouts.etc.. So worst case scenario a large area ,npc's, monsters, pc's all fighting. Problem is I like large areas with mixed melee's.
Funky: Could you like that anit-lag tutorial. I could use a brush up.
Thanks.
You should have said: Flogging an undead horse. But I suppose that a horse of a different color.
Modifié par ffbj, 08 février 2013 - 11:10 .





Retour en haut







