What is wrong with this?

For test results, bug reports, announcements of new builds etc.

Moderators: winston, another_commander, Getafix

Post Reply
User avatar
Lestradae
---- E L I T E ----
---- E L I T E ----
Posts: 3095
Joined: Tue Apr 17, 2007 10:30 pm
Location: Vienna, Austria

What is wrong with this?

Post by Lestradae »

Me being thick again:

Code: Select all

if((this.ship.target.isStation && this.ship.target.maxSpeed == 0) || this.ship.target.scanClass == "CLASS_ROCK") return
The log is complaining that
[script.javaScript.exception.noProperties]: ***** JavaScript exception ("rmb-law-missile-script" 1.0): TypeError: this.ship.target has no properties
[script.javaScript.exception.noProperties]: ../AddOns/A - OSE Main Data WiP V0.67.014.oxp/Scripts/rmb-law-missile-script.js, line 8.

... when using trunk, ingame if NPC versus NPC action is going on.

What is the problem here? As far as I believe to understand the line shall prevent certain objects such as rocks or stations from being stunned by a law missile.

So what the heck?

Answers would be helpful,

L
User avatar
Cmdr James
Commodore
Commodore
Posts: 1357
Joined: Tue Jun 05, 2007 10:43 pm
Location: Berlin

Post by Cmdr James »

Looks like this.ship.target is not defined, or there is a problem with it.

Have you tested that this.ship.target is set to something?
User avatar
Lestradae
---- E L I T E ----
---- E L I T E ----
Posts: 3095
Joined: Tue Apr 17, 2007 10:30 pm
Location: Vienna, Austria

..

Post by Lestradae »

Hm, NPC ships do have targets, if they fire a missile, like, i.e., a law missile, yes?

Otherwise the problem probably is that I give law missiles to NPCs and they can't use them properly?!?

Could that be it?
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6633
Joined: Wed Feb 28, 2007 7:54 am

Post by another_commander »

The best practice is to always check for target's existence, regardless of what you think the game should do. It might well be that some other script/code action that one might be unaware of is erasing the target and in this case you will see this message.

Just add one more check at the beginning of the if statement to ensure that there is a target before starting to check the properties of said target.
User avatar
Thargoid
Thargoid
Thargoid
Posts: 5528
Joined: Thu Jun 12, 2008 6:55 pm

Post by Thargoid »

It depends if they are losing their target for some reason (e.g. their target gets vape'd) and you're looking at the wrong time in their AI sequence. It does happen, at all sorts of odd times, given the polling cycle of things and things like pauses in AI's and such.

But the error does sound like the target isn't set, as the good Commander says. If you change the code to...

Code: Select all

if(!this.ship.target || (this.ship.target.isStation && this.ship.target.maxSpeed == 0) || this.ship.target.scanClass == "CLASS_ROCK") return
...to do a check that the target exists first then you should be fine.
User avatar
Lestradae
---- E L I T E ----
---- E L I T E ----
Posts: 3095
Joined: Tue Apr 17, 2007 10:30 pm
Location: Vienna, Austria

..

Post by Lestradae »

Thanks guys for the replies and thanks T, implemented your fix with the additional check.

Another question, I am having a look through scripts and noticed another thing concerning the law missile script, it says ...

Code: Select all

this.checkTargetVulnerability = function()
 {
if(!this.ship.target || (this.ship.target.isStation && this.ship.target.maxSpeed == 0) || this.ship.target.scanClass == "CLASS_ROCK") return
if(this.ship.target.isPlayer) return

else

        this.ship.target.setAI("rmb-stunnedAI.plist")

}
... I am still pretty much a n00b at this, shouldn't it be ...

Code: Select all

this.checkTargetVulnerability = function()
 {
if(!this.ship.target || (this.ship.target.isStation && this.ship.target.maxSpeed == 0) || this.ship.target.scanClass == "CLASS_ROCK") return
if(this.ship.target.isPlayer) return

else
        {
        this.ship.target.setAI("rmb-stunnedAI.plist")
        }
}
... instead, and if not, why not?

:?:

L
User avatar
Thargoid
Thargoid
Thargoid
Posts: 5528
Joined: Thu Jun 12, 2008 6:55 pm

Post by Thargoid »

Because the if..then..else code blocks are single lines (the return for true and the setAI for the else/false), it doesn't really matter in this case. The curly brackets {} basically just say "this is a single block section of code", and as your ones below are just single lines anyway they are optional.

If you're being really strict then the two return's should also have curly brackets around them, as they are similarly single lines of code, both performed when this if statements are true.
User avatar
Thargoid
Thargoid
Thargoid
Posts: 5528
Joined: Thu Jun 12, 2008 6:55 pm

Post by Thargoid »

You could equally write the code as (and optimise it a little)

Code: Select all

this.checkTargetVulnerability = function() 
 { 
if(!this.ship.target || this.ship.target.isPlayer || (this.ship.target.isStation && this.ship.target.maxSpeed == 0) || this.ship.target.scanClass == "CLASS_ROCK") return 
else 
        this.ship.target.setAI("rmb-stunnedAI.plist") 
}
which is equivalent to

Code: Select all

this.checkTargetVulnerability = function() 
{ 
 if(!this.ship.target || this.ship.target.isPlayer || (this.ship.target.isStation && this.ship.target.maxSpeed == 0) || this.ship.target.scanClass == "CLASS_ROCK")
        {
        return 
        }
 else 
        {
        this.ship.target.setAI("rmb-stunnedAI.plist") 
        }
}
The second if statement can be brought into the first one, as you're checking the same thing and will have the same desired result if true.
User avatar
Eric Walch
Slightly Grand Rear Admiral
Slightly Grand Rear Admiral
Posts: 5536
Joined: Sat Jun 16, 2007 3:48 pm
Location: Netherlands

Re: ..

Post by Eric Walch »

Lestradae wrote:
... I am still pretty much a n00b at this, shouldn't it be ...

Code: Select all

else 
        { 
        this.ship.target.setAI("rmb-stunnedAI.plist") 
        } 
Both is ok. The {} are only needed when there are more than one statements that belongs to the else. When you leave out the {} and use two statements, the first belongs to else and the second will be seen as something new, not belonging to the if()else(); statement and will always be executed.
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6633
Joined: Wed Feb 28, 2007 7:54 am

Post by another_commander »

Curly brackets usage in the case of single line statements is a matter of style and personal preference, but my humble recommendation - especially for people new to coding - would be to use them regardless of how many statements follow your if/else/while/whatever, because this clearly shows at first glance which code is intended for execution.

For example: Let's say I have a block which looks like this:

Code: Select all

if (ship == player)
    doSomethingWithPlayer();
Let's assume that I want to add a line that outputs a log statement before doSomethingWithPlayer for debugging reasons. One of the common mistakes a green coder would do is this:

Code: Select all

if (ship == player)
    log("I am doing something with the player ship");
    doSomethingWithPlayer();
Now we have just introduced a bug in the code. If ship equals player, then a log line will be written and then the doSomethingWithPlayer will be executed regardless of the if statement above, because it is considered an independent statement. The way it is indented, doSomethingWithPlayer looks as if it belongs to the if statement, but it really doesn't. One needs to remember to enter the curly brackets here.

If this had been written as

Code: Select all

if (ship == player)
{
    doSomethingWithPlayer();
}
from the beginning, then we can add the new log line in the block without worrying about the case described above. We'll just do a

Code: Select all

if (ship == player)
{
    log("I am doing something with the player ship");
    doSomethingWithPlayer();
}
and everything will work as expected. If the ship equals player, then both the log line and the doSomethingWithPlayer will be executed and if ship does not equal player then none of the two will be executed.

Hope this helps.
User avatar
Lestradae
---- E L I T E ----
---- E L I T E ----
Posts: 3095
Joined: Tue Apr 17, 2007 10:30 pm
Location: Vienna, Austria

.

Post by Lestradae »

another_commander wrote:
Hope this helps.
Yes it does :D

In retrospect what the brackets do seems that obvious now that I ask myself why I had to ask at all, but I guess that is always the case if something has been explained clearly.

8)

L
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

Cmdr James wrote:
Looks like this.ship.target is not defined, or there is a problem with it.
A technical note here: a ship’s target can never be undefined (like all permanent host-defined properties in Oolite, target cannot be deleted), but it can be null. Unlike most languages, these are distinct concepts in JavaScript. null is a placeholder value for properties or variables which don’t refer to anything useful but nevertheless exist – for instance, ship.target when the ship isn’t targeting anything. null is an object that has no properties, which explains the error Lestradae got. undefined, on the other hand, is the value of a property that doesn’t exist, like player.ship.willyWonka (unless you define it by assigning something to it).
Post Reply