AI not recognizing functions?
by Nathan Kent · in Technical Issues · 03/07/2008 (3:40 pm) · 9 replies
My AI aren't doing their functions. I keep getting that nodeScan, findNodes, and CorrectPath don't exist for AIPlayers. I'm not getting it:
function AIPlayer::nodeScan(%this) {
InitContainerRadiusSearch(%this.getPosition(), 2, $TypeMasks::PlayerObjectType);
while ((%targetObject = containerSearchNext()) != 0)
{
error("Someone coming close -- I'm " @ %this @ "and they're " @ %targetObject);
if (%targetObject.rank < %this.rank)
%this.assignNodes(%targetObject);
}
schedule(2000,'nodeScan', %this);
}
function AIPlayer::assignNodes(%this, %them) {
%curNode = %them.path.getObject(%them.currentNode);
%theirDist = VectorDist(%them.getPosition(), %curNode.getPosition());
%theyReq = %curNode.pathsNum == 1;
%curNode = %this.path.getObject(%this.currentNode);
%myDist = VectorDist(%this.getPosition(), %curNode.getPosition());
%meReq = %curNode.pathsNum == 1;
switch (%myDist < %theirDist) {
case 1:
if (%meReq && %theyReq)
%this.waitForNode();
else if(%meReq)
%them.correctPath();
else
%them.correctPath();
case 0:
if (%meReq && %theyReq)
%them.waitForNode();
else if(%theyReq)
%this.correctPath();
else
%them.correctPath();
}
}
function AIPlayer::findNodeNum(%this) {
%nodeStart = %this.path.getObject(%this.oldNode);
%nodecountStart = %nodeStart.pathsNum;
%nodeEnd = %them.path.getObject(%them.currentNode);
%nodecountEnd = %nodeEnd.pathsNum;
for (%i = 0; %i < %nodecountStart; %i++) {
%a = getWord(%nodeStart.paths, %i);
for (%y = 0; %y < %nodecountEnd; %y++) {
%b = getWord(%nodeEnd.paths, %y);
if(%b $= %y)
break;
}
if(%a $= %y)
break;
}
return %a;
}
function AIPlayer::correctPath(%this) {
%new = %this.findNodeNum();
while(%new $= %this.currentNode) {
%new = %this.findNodeNum();
}
%this.moveToNode(%new);
}
function AIPlayer::spawnPeasent(%name, %path, %node, %gender) {
%peasent = AIPlayer::spawnOnPath(%name, %path, %node, "PeasantAvatar", %gender);
schedule(2000, 'nodeScan', %peasent);
%peasent.setMoveSpeed(.15);
return %peasent;
}
//-----------------------------------------------------------------------------
// AIPlayer static functions
//-----------------------------------------------------------------------------
function AIPlayer::spawn(%name,%spawnPoint,%datablock)
{
// Create the demo player object
%player = new AiPlayer() {
dataBlock = %datablock;
path = "";
rank = $AIPlayer::count;
};
MissionCleanup.add(%player);
%player.setShapeName(%name);
%player.setTransform(%spawnPoint);
$AIPlayer::count++;
return %player;
}
function AIPlayer::spawnOnPath(%name, %path, %node,%datablock)
{
// Spawn a player and place him on the first node of the path
if (!isObject(%path))
return;
%node = %path.getObject(%node-1);
return AIPlayer::spawn(%name, %node.getTransform(),%datablock);
}About the author
#2
schedule() not working
Function [functionHere] not found for AIPlayer
03/08/2008 (4:12 am)
Errors:schedule() not working
Function [functionHere] not found for AIPlayer
#3
03/08/2008 (1:12 pm)
I've had considerable issues trying to create new functions in namespaces in script--exactly like what you've got. I solved it by simply removing it from the namespace, as in, changing AIPlayer::spawnOnPath to plain old spawnOnPath and then calling it appropriately.
#4
03/08/2008 (1:58 pm)
I as well, Lee, especially with schedules. Sometimes you just have to change the order for some ungodly reason. The "%this" parameter is just too useful to totally throw out using namespaces.
#5
03/09/2008 (5:24 am)
I tried that, but the scedule still won't call.
#6
schedule(2000,0,'nodeScan', %this);
You need the field where the 0 is. I think this is supposed to be an object the schedule is dependent on, but I haven't seen that work, yet. Zero will be fine for testing purposes.
03/09/2008 (6:31 am)
Your syntax isn't quite right. Try something like:schedule(2000,0,'nodeScan', %this);
You need the field where the 0 is. I think this is supposed to be an object the schedule is dependent on, but I haven't seen that work, yet. Zero will be fine for testing purposes.
#7
In my experience, creating a function based on a namespace should look like this:
Whenever you use a namespace to define a function, you should include %this as the first parameter, and any object to call the function should treat it like a "built-in" function.
Thus you can reference the object that calls the function as %this no matter what.
As far as scheduling goes:
If you are calling a function that has a namespace, use this scheduling method:
What Lee is thinking of is scheduling global functions such as quit() or activateKeyboard():
After writing all of this, I realized that this wasn't in the TGB forums. Well, the above is what works in TGB %100 of the time.
03/09/2008 (7:30 am)
Perhaps its my programming ignorance speaking here, but does including the namespace itself in a function call ever work? There seems to be some major problems with the syntax of your entire block of code.In my experience, creating a function based on a namespace should look like this:
function playerClass::executeAttack(%this, %param1, %param2)
{
}When you call the above function, it would look like this:player.executeAttack("swing", 15);Obviously, %param1 is a string and %param2 is an integer. Notice however that since "executeAttack" has a namespace, you say %object.executeAttack(. . . ) instead of passing in an object in the parameters.Whenever you use a namespace to define a function, you should include %this as the first parameter, and any object to call the function should treat it like a "built-in" function.
Thus you can reference the object that calls the function as %this no matter what.
As far as scheduling goes:
If you are calling a function that has a namespace, use this scheduling method:
%object.schedule([%time integer], [%functionName string], [%arg1 . . . %argN]); %peasent.schedule(2000, "nodeScan");Note that any function with a namespace will automactically receive the object that calls a schedule, in the above fashion, as %this.
What Lee is thinking of is scheduling global functions such as quit() or activateKeyboard():
schedule([%time integer], [%referenceObject integerID OR 0 for a GLOBAL function], [%functionName string], [%arg1 . . . %argN]); schedule(2000, %peasent, "nodeScan"); schedule(2000, 0, "quit");
After writing all of this, I realized that this wasn't in the TGB forums. Well, the above is what works in TGB %100 of the time.
#8
03/09/2008 (8:19 am)
"schedule(2000,'nodeScan', %this);" isn't dealing with the namespace. It's trying to call the function "nodeScan" which doesn't exist. Without calling schedule on the AIPlayer, you would need to do:schedule(2000, 0, "AIPlayer::nodeScan", %this);I'm pretty sure you could do that and have it work, but try doing this first:
%this.schedule(2000, "nodeScan");
#9
03/10/2008 (4:49 am)
I figured out the problem, I was using 'nodeScan' when it should've been "nodeScan". I hate stupid typos like that, mess up your programming, but to small to get an error from it.
Torque Owner Lee Latham
Default Studio Name