View previous topic :: View next topic |
Author |
Message |
weldieran
Joined: 05 Aug 2005 Posts: 71
|
Posted: Tue Aug 16, 2005 21:29 Post subject: Use of SQLFetch() and TMI Errors |
|
|
OK - I've been getting some TMI errors i'm trying to track down.
I wonder if it has to do with my use of SQLFetch.
Code: |
while (SQLFetch() == SQL_SUCCESS)
{
iCount++;
}
|
Is something like that possible with aps?
Or if it returns one record, will it be SQL_SUCCESS to infinite? |
|
Back to top |
|
|
weldieran
Joined: 05 Aug 2005 Posts: 71
|
Posted: Tue Aug 16, 2005 21:32 Post subject: |
|
|
look at the Fetch code, it does seem it was made for that.. hmm.. perhaps i'm barking up the wrong tree, but can anyone confirm? |
|
Back to top |
|
|
weldieran
Joined: 05 Aug 2005 Posts: 71
|
Posted: Tue Aug 16, 2005 22:56 Post subject: |
|
|
ok, yes, barked up the wrong tree.
Apparently looping thru certain PCs inventories causes this.
Anyone know how many instructions before bioware cancels with TMI Error?
The PC in question had a recorded value of 413 - and i am not even sure if that was totally accurate.
Anyone know how I could possibly NOT loop through 99 arrows in a stack? I think its ridiculous that it would loop 99 times on 99 arrows when each time it returns the SAME EXACT VALUE as the other arrows in the stack. Same object, same stacksize, same stacked amt, etc. ARG! |
|
Back to top |
|
|
Acrodania
Joined: 02 Jan 2005 Posts: 208
|
Posted: Wed Aug 17, 2005 0:06 Post subject: |
|
|
Looping through stacked items is a known issue and one reason that some PWs don't allow magic bags/bags of holding. No way around it.... I know that I have several players that between arrows and potions can run over 10k things in their inventory. Pack rats!
I read in a thread back a while ago that the maximum executions (loop, GetVariable, etc) you could perform in a single script before getting a TMI was around 65,000 which makes some sense if its a 16 bit stack (65,536). It seems like a lot but its really easy to to hit. |
|
Back to top |
|
|
Alosynth
Joined: 06 Jan 2005 Posts: 24
|
Posted: Wed Aug 17, 2005 3:02 Post subject: |
|
|
I don't know how this would work for looping through inventories, but it might be worth a shot.
You could put a fail-safe into main loop that stops it from looping after a certain number of loops (say 100) when/if that number is hit, the loop breaks and a recursive function is called that continues to go through another 100 items before breaking and re-calling itself. I don't believe that there is a GetNthItemInInventory type function, but if you include the last object that was set as the focused object, using GetNext should continue on without skipping or repeating any items in inventory.
For example:
Code: | DoInventoryLoop (object oItem) {
int nCount = 0;
while(GetIsObjectValid(oItem) && nCount <= 100) {
{/* Do what ever it is your doing with the items here */}
++nCount;
oItem = GetNextItemInInventory(oPC);
}
// if there is still a valid item, do it again, else we're done
if(GetIsObjectValid(oItem)) {
DelayCommand(1.0, DoInventoryLoop(oItem));
}
}
void main () {
object oPC; // Define the PC in some way
object oItem = GetFirstItemInInventory(oPC);
DoInventoryLoop(oItem);
} |
It may need some tweaking to do what you need (or even to work) since I just wrote this off the top of my head and have never tried this. |
|
Back to top |
|
|
dguntner
Joined: 31 Dec 2004 Posts: 116
|
Posted: Wed Aug 17, 2005 4:46 Post subject: |
|
|
weldieran - now there's a name I haven't seen in a while....
You're right, Alosynth - players do tend to be pack-rats. And with a persistent container, once TMI is hit, they tend to lose whatever might have been left in the database table storing their stuff. Thanks for posting that - you reminded me that I need to do something along the lines of what you posted, to keep the TMIs away.
--Dave |
|
Back to top |
|
|
weldieran
Joined: 05 Aug 2005 Posts: 71
|
Posted: Wed Aug 17, 2005 17:48 Post subject: |
|
|
But wouldn't it be necessary to utilize ExecuteScript in your theory Alosynth?
If its 65k instructions allowed per script before TMI, then your example would n't do the trick would it?
And then if we did use executescript, do you still think "GetNextItemInInventory" will still truly call the next item - being that it is in seperate script?
And does ExecuteScript really get its own max before TMI, or is it all added together to the main calling script?
I did a test on an inventory stocked full of 99 arrow stacks. For each item in inventory, I wrote ObjectToString to the log. It didn't report 99 arrows in each stack, but rather just the stacks themselves.
So is this perhaps an old tale no longer true? I would've expected 99 of the same ObjectToString for each stack *boggle* |
|
Back to top |
|
|
Primogenitor
Joined: 08 Jan 2005 Posts: 88
|
Posted: Wed Aug 17, 2005 21:12 Post subject: |
|
|
weldieran wrote: | But wouldn't it be necessary to utilize ExecuteScript in your theory Alosynth?
If its 65k instructions allowed per script before TMI, then your example would n't do the trick would it?
| The delay command splits it up. You can use either ExecuteScript or DelayCommand.
Quote: |
And then if we did use executescript, do you still think "GetNextItemInInventory" will still truly call the next item - being that it is in seperate script? | Yes, provided nothing else changes the pointer e.g. deleting an item, adding an item, a different loop.
Quote: | I did a test on an inventory stocked full of 99 arrow stacks. For each item in inventory, I wrote ObjectToString to the log. It didn't report 99 arrows in each stack, but rather just the stacks themselves.
So is this perhaps an old tale no longer true? I would've expected 99 of the same ObjectToString for each stack *boggle* | The problem is with containers. Since a container basically expands the inventory space of the PC, if each container is full of small items, such a potion stacks or arrow stacks, plus the original inventory is full of containers, the loop gets very very large. |
|
Back to top |
|
|
Papillon x-man
Joined: 28 Dec 2004 Posts: 1060 Location: Germany
|
Posted: Wed Aug 17, 2005 23:09 Post subject: |
|
|
It's also interesting that the hardcoded maximum number of instructions before a TMI occurs is measured in virtual machine instructions - which resembles assembler a bit, i.e. NWScript instructions are resolved into several small VM instructions. That's the main reason why one loop TMI's while another similar one does not.
It also only counts towards the maximum if there is no interruption in between, which can be caused e.g. by ExecuteScript. Each interruption resets the counter. _________________ Papillon |
|
Back to top |
|
|
weldieran
Joined: 05 Aug 2005 Posts: 71
|
Posted: Wed Aug 17, 2005 23:26 Post subject: |
|
|
Good to know execute script resets that counter.
In my own tests, it appears that when a PC first enters the world, it processes all the inventory (on acqurie fires for each item) before it fires onClientEnter.
However, it seems there are sometimes when this doesn't happen? Anyone have any definitives about this?
Some people end up with two PCWands when they should only EVER have one. The onClientEnter checks for the item, if not found, creates one. So why is it onClientEnter sometimes seems to fire before all the inventory is on the person?
is it just me or is biowares crap extremely querky? |
|
Back to top |
|
|
Acrodania
Joined: 02 Jan 2005 Posts: 208
|
Posted: Thu Aug 18, 2005 0:59 Post subject: |
|
|
From what I've heard others discussing (with situations like yours) is that when the character enters the module, it cycles the entire PC's inventory and fires the OnAquire script for each one.
I solved my issues with OnEnter() not creating/finding items correctly by using a DelayCommand of 5 seconds and doing all my checks in that script instead of the default OnEnter(). |
|
Back to top |
|
|
Primogenitor
Joined: 08 Jan 2005 Posts: 88
|
Posted: Thu Aug 18, 2005 9:10 Post subject: |
|
|
Yes, last time I checked it fires OnAquire for all items, OnEquip for all equiped items, then it fires the module OnEnter, then the areas OnEnter. I dont know if it doesnt fire events and/or fires twice in any conditions, but I suspect it may be lag-related (i.e in a small test it doesnt, but in a "real" module it does). |
|
Back to top |
|
|
weldieran
Joined: 05 Aug 2005 Posts: 71
|
Posted: Sat Aug 20, 2005 22:09 Post subject: onClientExit |
|
|
Anyone know if onClientExit is fired properly for all logged in when server has been given command "exit" or "quit"?
Been having issues of loss of data, and i believe its due to onClientExit not firing on PCs when server performs a normal shutdown. |
|
Back to top |
|
|
dguntner
Joined: 31 Dec 2004 Posts: 116
|
Posted: Sat Aug 20, 2005 22:28 Post subject: |
|
|
OnClientLeave fires, but from day one of this game, certain information about the exiting player is not available about the exiting player. GetPCPlayerName(), for one, will not function and will just return an empty string (because at that point the player is no longer in the game). I believe there are other things which also do not fucntion for the same reasons. Whether they leave the game via logging out or the server shutting down makes no difference.
--Dave |
|
Back to top |
|
|
Primogenitor
Joined: 08 Jan 2005 Posts: 88
|
Posted: Sun Aug 21, 2005 12:20 Post subject: |
|
|
Any of the GetPC* fucntions I think fail to work. The solution is store then as local variable on the player when they log in. |
|
Back to top |
|
|
|