Game Development Community

Specialized AI Bot

by dragonlady · in Technical Issues · 12/13/2007 (4:52 pm) · 12 replies

Hello again everyone! Once again I need assistance from all the brilliant Torque minds here :) I've been looking at this problem for a week and can't make heads or tails of it.

I'm having trouble with my AI bot, called FirewoodGuy. He's supposed to be a subclass of the regular AI bots. I want him to see if the player is within a certain distance, and if he is, the FWGuy should yell at him to not steal firewood. When I create the bot in spawnOnPath, I first created a new FirewoodGuy, but the console gave me an error saying I couldn't instantiate a non-cons class (not sure what that means). So I created it as a new AIPlayer, with the FWGuy datablock associated, but now when I try to call FWGuy functions, the console gives me a message that the function cannot be found. And then it shows an inheritance hierarchy chain, which goes from Player on up. I'm probably going about creating my bot incorrectly, but how can I get it to recognize the functions that are associated with FWGuy?

Here's the code:

datablock PlayerData(FirewoodGuy)
{
shapeFile = "~/data/shapes/player/player.dts";
};

function FirewoodGuy::spawn(%name,%spawnPoint)
{
// Create the demo player object
%player = new AIPlayer() {
dataBlock = FirewoodGuy;
path = "";
};
MissionCleanup.add(%player);
%player.setShapeName(%name);
%player.setTransform(%spawnPoint);
return %player;
}

function FirewoodGuy::spawnOnPath(%name,%path)
{
echo("spawning fire guy");
// Spawn a player and place him on the first node of the path
if (!isObject(%path))
return;
%node = %path.getObject(0);
%player = FirewoodGuy::spawn(%name,%node.getTransform());
%player.followPath( "MissionGroup/myPath", -1 );
%player.think();
return %player;
}

function FirewoodGuy::think(%this)
{
if( !isObject( %this.player ) )
%this.player = %this.spawn();
%this.isPlayerInRange(%this);
%this.schedule( 500, think );
}

function FirewoodGuy::getClosestPlayer(%this)
{
%botPos = %this.getPosition();
%playerCount = ClientGroup.getCount();
for(%i = 0; %i < %playerCount; %i++)
{
%player = ClientGroup.getObject(%i);
%playerPos = %client.player.getPosition();
%tempDist = VectorDist(%playerPos, %botPos);
if(%i == 0)
{
%dist = %tempDist;
%index = %i;
}
else {
if(%dist > %tempDist) {
%dist = %tempDist;
%index = %i;
}
}
}
return %index;
}

function FirewoodGuy::isPlayerInRange(%this)
{
%player = %this.getClosestPlayer();
%playerPos = %player.getPosition();
%dist = VectorDist(%playerPos, %this.getPosition());
if(%dist <= 20)
{
messageClient(%player.client, 'MsgItemFound', 'Stay away from my stuff!');
}
else
{
messageClient(%player.client, 'MsgItemFound', 'Not in range.');
echo("not in range");
}
}




Just to see what would happen, I also changed the functions think, getClosestPlayer, and isPlayerInRange to be member functions of AIPlayer. When I did that, the functions were found, but the getPosition calls in the isPlayerInRange and getClosestPlayer calls resulted in the following error messages in my console log:

demo/server/scripts/FirewoodGuy.cs (116): Unable to find object: '' attempting to call function 'getPosition'
demo/server/scripts/FirewoodGuy.cs (136): Unable to find object: '0' attempting to call function 'getPosition

And BTW, I borrowed some of this code from a helpful resource I found on scripting advanced AI bots, posted by Stefan Beffy Moises.

Thanks everyone!

#1
12/13/2007 (5:18 pm)
What is the exact console error you are getting when the function is getting called?
#2
12/13/2007 (5:33 pm)
Did you put the exec in the game.cs?
#3
12/13/2007 (5:36 pm)
Steve D, these are the following errors that I get in each situation I've tried:

When all the functions are associated with datablock FirewoodGuy, and the bot is created as an AIPlayer associated with FirewoodGuy datablock:
demo/server/scripts/FirewoodGuy.cs (97): Unknown command think.
Object (2141) AIPlayer -> Player -> ShapeBase -> GameBase -> SceneObject -> NetObject -> SimObject

When I create the bot as a FirewoodGuy with the statement %player = new FirewoodGuy() {
dataBlock = FirewoodGuy;
path = "";
};
demo/server/scripts/FirewoodGuy.cs (81): Unable to instantiate non-conobject class FirewoodGuy

And then when I create the bot as an AIPlayer, and associate the functions with AIPlayer:
demo/server/scripts/FirewoodGuy.cs (116): Unable to find object: '' attempting to call function 'getPosition'
demo/server/scripts/FirewoodGuy.cs (136): Unable to find object: '0' attempting to call function 'getPosition
#4
12/13/2007 (5:37 pm)
Tyler: the exec is in the game.cs script; the FWGuy bot actually does show up in the game and runs around the path, when I create him as an AIPlayer, but his functions don't work.
#5
12/13/2007 (6:02 pm)
I could be wrong and without working through this in detail I think the problem might be you are treating the functions as if they are part of a scriptobject when they are stand alone functions.

I don't see how the %player.think() will work when the %player variable is just the aibot object id.

Something you can try is call the think function spawnonpath passing it the %player variable, so try firewoodguy::think(%player) this way the objectid will get passed.
#6
12/13/2007 (6:33 pm)
Hmmmm....I tried your suggestion Steve, yet the problem still persists. I'm noticing that even in the following line:

%playerPos = %client.player.getPosition();

I get the error: Unable to find object: '' attempting to call function 'getPosition'

What interests me about that line, is that it is preceded by the following lines:
%playerCount = ClientGroup.getCount();
for(%i = 0; %i < %playerCount; %i++)
{
%player = ClientGroup.getObject(%i);

So the player that I'm getting the position of should be taken straight from the client list, and my avatar is the only client, and since I was created correctly and didn't tamper with the Player script that created me, shouldn't my avatar at least be passed as a valid object? (I hope that made sense; if not I can try to explain what I'm getting at a little better).
#7
12/13/2007 (6:59 pm)
Hmmmm....I tried your suggestion Steve, yet the problem still persists. I'm noticing that even in the following line:

%playerPos = %client.player.getPosition();

I get the error: Unable to find object: '' attempting to call function 'getPosition'

What interests me about that line, is that it is preceded by the following lines:
%playerCount = ClientGroup.getCount();
for(%i = 0; %i < %playerCount; %i++)
{
%player = ClientGroup.getObject(%i);

So the player that I'm getting the position of should be taken straight from the client list, and my avatar is the only client, and since I was created correctly and didn't tamper with the Player script that created me, shouldn't my avatar at least be passed as a valid object? (I hope that made sense; if not I can try to explain what I'm getting at a little better).
#8
12/13/2007 (7:06 pm)
To add to my last post, I did some messing around on the console in the game. Here's what I did:

==>echo(ClientGroup.getObject(0));
1689
Sending heartbeat to master server [IP:69.64.50.217:28002]
==>%player = ClientGroup.getObject(0);
==>echo(%player);

Received info request from a master server [IP:69.64.50.217:28002].
==>echo(%player.getName());
(0): Unable to find object: '' attempting to call function 'getName'

==>echo(1689.getName());
LocalClientConnection

So basically, I started by getting the first object in the client group (should be my avatar). The handle for that was 1689. When I assigned the first object in the client group in to a variable and then tried to output it, it came up blank. To further test this, when I tried to output the name of the object using its handle, I successfully saw output. Yet when I tried to do the same thing via the %player variable, I got the "unable to find object" error. So for some reason, nothing is being stored in the variable, which seems to be related to my getPosition problem.
#9
12/13/2007 (7:18 pm)
I'm afraid I really can't help you, it's hard to work through something when you are only seeing pieces. You could zip up your mission file an server scripts and email them to me and I'll try and run the game and see it as you're seeing it and figure out the problem.

I don't know if you have it already but I highly recommend purchasing Torsion, it's invaluable for debugging these kinds of problems.
#10
12/13/2007 (7:35 pm)
To add to my last post, I did some messing around on the console in the game. Here's what I did:

==>echo(ClientGroup.getObject(0));
1689
Sending heartbeat to master server [IP:69.64.50.217:28002]
==>%player = ClientGroup.getObject(0);
==>echo(%player);

Received info request from a master server [IP:69.64.50.217:28002].
==>echo(%player.getName());
(0): Unable to find object: '' attempting to call function 'getName'

==>echo(1689.getName());
LocalClientConnection

So basically, I started by getting the first object in the client group (should be my avatar). The handle for that was 1689. When I assigned the first object in the client group in to a variable and then tried to output it, it came up blank. To further test this, when I tried to output the name of the object using its handle, I successfully saw output. Yet when I tried to do the same thing via the %player variable, I got the "unable to find object" error. So for some reason, nothing is being stored in the variable, which seems to be related to my getPosition problem.
#11
12/13/2007 (7:39 pm)
To add to my last post, I did some messing around on the console in the game. Here's what I did:

==>echo(ClientGroup.getObject(0));
1689
Sending heartbeat to master server [IP:69.64.50.217:28002]
==>%player = ClientGroup.getObject(0);
==>echo(%player);

Received info request from a master server [IP:69.64.50.217:28002].
==>echo(%player.getName());
(0): Unable to find object: '' attempting to call function 'getName'

==>echo(1689.getName());
LocalClientConnection

So basically, I started by getting the first object in the client group (should be my avatar). The handle for that was 1689. When I assigned the first object in the client group in to a variable and then tried to output it, it came up blank. To further test this, when I tried to output the name of the object using its handle, I successfully saw output. Yet when I tried to do the same thing via the %player variable, I got the "unable to find object" error. So for some reason, nothing is being stored in the variable, which seems to be related to my getPosition problem.
#12
12/13/2007 (7:40 pm)
I understand what you mean, Steve. I tutor people in C++, and it's difficult if you can't run the program through yourself. I'm sending you a zip file at the email address in your profile.

I appreciate your help :)