Scripting help: Avoiding script freezes

The place to discuss scripting and game modifications for X³: Terran Conflict and X³: Albion Prelude.

Moderators: Moderators for English X Forum, Scripting / Modding Moderators

Post Reply
Cronos988
Posts: 678
Joined: Mon, 27. Aug 07, 12:34

Scripting help: Avoiding script freezes

Post by Cronos988 » Sun, 23. Sep 12, 15:20

Dear Scripting and modding community,

I am currently working on a script that is intended to improve the group attack behaviour of formations. It ties into the standard protect command and replaces the 'attack first attacker' with a targeting script that analyzes the enemy formation and then decides what target to attack.

The script itself is working. However, it is causing random game freezes that I cannot reproduce by testing.

I have an empty testing universe that I use for putting various groups of ships against each other, and in all my tests, I only got 1 freeze, unfortunately while I was looking at my code. Yet when I play the game, I get a freeze roughly every 5 minutes. The script runs on all ships that are using protect commands, so it is likely called a lot.

It is probably a rare combination of events, but it happens often enough to make the game unplayable.

Since I cannot reproduce the error, I wanted to broaden my understanding of what can cause game freezes.

I know a while loop will freeze the game if it runs indefinetly. However, my only while loops are loops on ship arrays, which are rather safe, and and a waiting loop that checks a local until it turns "!= TRUE". The latter has a ton of safety nets in it though, including a counter that breaks it after 20 runs.

Apart from that, I am at a loss at what might cause the lockups.
Here are some of the things I do:

- Store ship stats as a local variable once and then have the targeting script read these locals

- Store every attacker of a given ship as a local array on the attacked ship. When another ship attacks, it checks who is already attacking the target to see if it should also attack. It also checks whether the stored ships are still alive and attacking.
This requires reading and setting a local array as well as a "lock" local to prevent multiple ships from modifying the array at the same time.

- Fight attack object is called, and afterwards the ship checks for other attackers on itself and the leader. if it finds anything, it repeats the entire script. if not, it runs a cleanup that deletes the stored enemy array on itself.

What I know is that neither ships dying nor ships bailing by itself causes a crash. Neither does the game crash when one of the groups has been entirely destroyed.

So has anyone any tips as to what to look out for, or what functions to avoid?

User avatar
Nividium
Posts: 695
Joined: Tue, 21. Aug 07, 01:31

Re: Scripting help: Avoiding script freezes

Post by Nividium » Sun, 23. Sep 12, 16:25

Cronos988 wrote:I know a while loop will freeze the game if it runs indefinetly. However, my only while loops are loops on ship arrays, which are rather safe,...
Rule of thumb. Always put a @wait at the end of a While loop no matter what. Even a 5ms wait can make all the dif. What I mean is locate the wait within the loop and near the end.

User avatar
Litcube
Posts: 4239
Joined: Fri, 20. Oct 06, 19:02

Post by Litcube » Sun, 23. Sep 12, 17:40

If it's not infinite loops causing your problem, STARTing a script on an object that doesn't exist can lock it up.

In a test environment with little going on, waits in loops happen quickly, quick enough to catch if an object exists even if it's sloppy code.

A real environment, 15,000 tasks for example, sloppy code is less forgiving. Waits in this case can take up to a second. A lot can happen in a second, such as a ship dying. If it's dead, and you didn't expect it, you can START a command on it.

Cronos988
Posts: 678
Joined: Mon, 27. Aug 07, 12:34

Post by Cronos988 » Mon, 24. Sep 12, 14:08

I am not using any START scripts, all scripts are called, which should interrupt if Signal_Killed was fired.

Maybe it's trying to set a local on a "null" object? I think I put in safety checks in front of every "set local", but maybe I missed an instance. The longer processing time due to higher load is a good tip, are there any other causes for script freezes that have something to do with objects dieing/ bailing?

User avatar
Gazz
Posts: 12423
Joined: Fri, 13. Jan 06, 17:39

Re: Scripting help: Avoiding script freezes

Post by Gazz » Mon, 24. Sep 12, 14:48

Cronos988 wrote:- Store every attacker of a given ship as a local array on the attacked ship. When another ship attacks, it checks who is already attacking the target to see if it should also attack. It also checks whether the stored ships are still alive and attacking.
I did something similar (never released it) but since all arrays are pointers, I kept that attacker list for entire wings or formations.

If a ship attacks "a" member of a formation, it's instantly known to all because they all access the same array.
Also keeps cleanup to a minimum. Destroyed ships and such are cleaned off all lists at once.

But yes, with combat scripts you do have to pay attention to "exist" and "same environment".
They are quick checks, anyway.
skip if BLAH exist,
continue...

I don't know a related crash issue offhand but some script instructions behave strangely when comparing objects in different environments.
My complete script download page. . . . . . I AM THE LAW!
There is no sense crying over every mistake. You just keep on trying till you run out of cake.

Cronos988
Posts: 678
Joined: Mon, 27. Aug 07, 12:34

Re: Scripting help: Avoiding script freezes

Post by Cronos988 » Mon, 24. Sep 12, 18:24

Gazz wrote:
Cronos988 wrote:- Store every attacker of a given ship as a local array on the attacked ship. When another ship attacks, it checks who is already attacking the target to see if it should also attack. It also checks whether the stored ships are still alive and attacking.
I did something similar (never released it) but since all arrays are pointers, I kept that attacker list for entire wings or formations.

If a ship attacks "a" member of a formation, it's instantly known to all because they all access the same array.
Also keeps cleanup to a minimum. Destroyed ships and such are cleaned off all lists at once.

But yes, with combat scripts you do have to pay attention to "exist" and "same environment".
They are quick checks, anyway.
skip if BLAH exist,
continue...

I don't know a related crash issue offhand but some script instructions behave strangely when comparing objects in different environments.
I too had the leader keep the arrays at first, but I had issues with my interrupts on the followers firing corretly and consequently decided to do a "swarm intelligence" where everyone looks for it's own targets, taking into account all other nearby ships.

It seems I have found the source: after commenting out my cleanup code (or rather shortening it to a return null), I have had no more crashes. I will need a cleanup method though or I will gradually slow my game to a halt.

How do I best clean invalid entries from an array?
I am thinking about cycling through the array, storing all valid entries in a new array and then writing back the new one.

Cronos988
Posts: 678
Joined: Mon, 27. Aug 07, 12:34

Post by Cronos988 » Mon, 24. Sep 12, 22:08

After some tweaks, I narrowed the problem down to my local variable 'arr.lock' (name abridged) being set to TRUE (or 1, or 2, I tested several variants) permanently.

However, this local is only set to TRUE when the array is being modified and then set to FALSE immediately afterwards.
There are no interrupt points in between the setting to true and the setting to false. Consequently, even the writing ship getting killed in the process should not interrupt the script.

Plus, there are only 2 to 10 lines of script between locking and unlocking, which does not explain every ship having the local set to locked.

Edit: Maybe I should not code so late...
It was simple, I put in one safety check to many which enabled the script to terminate before unlocking. Bad idea.

Anyways, contrary to my previous statement, the script freeze is back and I still have no clue what might cause it.

I am constantly rewriting parts of the script or commenting them out, but nothing seems to help.
I noticed that there are noticeable lags sometimes when a ship dies, I get a couple of those and then a complete freeze. Maybe something accumulates somewhere.

I tested setting local variables on a "null" and calling scripts on "null", neither produces a freeze.

My next move will be to remove the "arr.lock" portions from the script. Will lead to some wrong resuslts, but I still think it has something to do with those.

Post Reply

Return to “X³: Terran Conflict / Albion Prelude - Scripts and Modding”