Author Topic: Need help fixing a simple AI. Crashes game.  (Read 1196 times)

I'm trying to make zombies that will chase a player if it's close enough, but if not will move towards the nearest light. So I took a script I found and tried to add the light code.
Here's my code:
Code: [Select]
$Pref::Bot::Intelligence = 500; // raise to max of 1000, 500 default
$Pref::Bot::MaxLightDist = 300;
$Pref::Bot::MinLightDist = 7;
$Pref::Bot::MaxPlayerDist = 50;
 
deactivatepackage(dren);
package dren
{
 
function AIPlayer::canSeeObject(%this, %object)
{
        %ev = %this.getEyeVector();
        %pos = %this.getPosition();
        if(!isObject(%object))
                return 0;
        if(isFunction(%object.getClassname(), getEyePoint))
                %ep = %object.getEyePoint();
        else
                %ep = %object.getPosition();
        %vd = vectorDist(%pos, %ep);
        if(%vd > 64)
                return 0;
        %cast = containerRaycast(%pos, %ep, $TypeMasks::FxBrickObjectType);
        if(isObject(%cast))
                return 0;
        %adjp = vectorSub(%pos, %ep);
        %angle = mATan(getWord(%adjp,1), getWord(%adjp,0));
        %ea = mATan(getWord(%ev,1), getWord(%ev,0));
        %cansee = %ea - %angle;
        %canSee = mAbs(%canSee);
        if(%cansee > 3.92689 || %cansee < 2.35629)
                return 0;
        return 1;
}
 
function AIPlayer::canSeePos(%this, %ep)
{
        %ev = %this.getEyeVector();
        %pos = %this.getPosition();
        %vd = vectorDist(%pos, %ep);
        if(%vd > 64)
                return 0;
        %cast = containerRaycast(%pos, %ep, $TypeMasks::FxBrickObjectType);
        if(isObject(%cast))
                return 0;
        %adjp = vectorSub(%pos, %ep);
        %angle = mATan(getWord(%adjp,1), getWord(%adjp,0));
        %ea = mATan(getWord(%ev,1), getWord(%ev,0));
        %cansee = %ea - %angle;
        %canSee = mAbs(%canSee);
        if(%cansee > 3.92689 || %cansee < 2.35629)
                return 0;
        return 1;
}
 
function closestLight(%pos)
{      
        %closestplayer = -1;
        %closestdist = -1;
        for(%a=0;%a<$numlights;%a++)
        {
                %playerpos = $lightpos[%a];
                if(%closestdist == -1 || vectorDist(%pos,%playerpos) < %closestdist)
                {
                        %closestdist = vectorDist(%pos,%playerpos);
                        %closestplayer = %a;
                }
        }
        return %closestplayer;
}
 
function AIPlayer::doThinkMove(%this)
{
        if(isObject(%this.getMoveObject()))
                %this.setMoveObject(0);
        %ev = %this.getEyeVector();
        %pos = %this.getPosition();
        for(%i = 0; %i < clientGroup.getCount(); %i++)
        {
                if(!isObject(%o = clientGroup.getObject(%i).player))
                        continue;
                if(%o.getObjectMount() == %this.getID())
                        continue;
                %ep = %o.getEyePoint();
                %vd = vectorDist(%pos, %ep);
                if(%vd > $Pref::Bot::MaxPlayerDist)
                        continue;
                %cast = containerRayCast(%pos, %ep, $TypeMasks::FxBrickAlwaysObjectType);
                if(isObject(%cast))
                        continue;
                %adjp = vectorSub(%pos, %ep);
                %angle = mATan(getWord(%adjp,1), getWord(%adjp,0));
                %ea = mATan(getWord(%ev,1), getWord(%ev,0));
                %cansee = %ea - %angle;
                %canSee = mAbs(%canSee);
                if(%cansee > 3.92689 || %cansee < 2.35629)
                        continue;
                if(%vd > %closestDist && %closestDist !$= "")
                        continue;
                %closestDist = %vd;
                %closestObj = %o;
        }
        if(isObject(%closestObj))
        {
                %this.chasePlayer(%closestObj, %closestDist);
                return;
        }
        else if((closestLight(%this.position) > -1) && vectorDist($lightpos[closestLight(%this.position)],%this.position) > $Pref::Bot::MinLightDist && vectorDist($lightpos[closestLight(%this.position)],%this.position) < $Pref::Bot::MaxLightDist)
        {
                %this.moveSchedule = %this.schedule(100,chaseLight,$lightpos[closestLight(%this.position)]);
                return;
        }
        %this.goToPos(vectorAdd(%this.getPosition(), getRandom(-5,5) SPC getRandom(-5, 5) SPC 0));
        %this.moveSchedule = %this.schedule(1000, doThinkMove);
}
 
function aiPlayer::goToPos(%this, %pos)
{
        %this.thinkNextMove(%pos);
}
 
function aiPlayer::ChasePlayer(%this, %player)
{
        if(!isObject(%player))
        {
                %this.doThinkMove();
                return;
        }
        if(%player.getState() !$= "Move" || vectorDist(%this.getPosition(),%player.getPosition()) > $Pref::Bot::MaxPlayerDist)
        {
                %this.doThinkMove();
                return;
        }
        if(%this.canSeeObject(%player))
        {
                %this.setMoveObject(%player);
                if(vectorDist(%this.getPosition(),%player.getPosition()) < 4 && %player.getState() $= "Move")
                        %this.attack(%player);
                if(isObject(%player) && %player.getState() !$= "")
                        %this.moveSchedule = %this.schedule(500, chasePlayer, %player);
                else
                        %this.doThinkMove();
                //announce("Returning");
                return;
        }
        if(isObject(%this.getMoveObject()))
                %this.setMoveObject(0);
        //announce("dynamic chase");
        %this.thinkNextMove(%player);
        %this.moveSchedule = %this.schedule(1000-$Pref::Bot::Intelligence, chasePlayer, %player);
}
 
function aiPlayer::ChaseLight(%this, %pos)
{
        if(closestLight(%this.position) == -1)
        {
                %this.doThinkMove();
                return;
        }
        if(vectorDist(%this.getPosition(),%pos) > $Pref::Bot::MaxLightDist || vectorDist(%this.getPosition(),%pos) < $Pref::Bot::MinLightDist)
        {
                %this.doThinkMove();
                return;
        }
        if(%this.canSeePos(%pos))
        {
                %this.moveSchedule = %this.schedule(500, chaseLight, %pos);
                return;
        }
        if(isObject(%this.getMoveObject()))
                %this.setMoveObject(0);
        %this.thinkNextMove(%pos);
        %this.moveSchedule = %this.schedule(1000-$Pref::Bot::Intelligence, chaseLight, %pos);
}
 
function AIPlayer::attack(%this, %player)
{
        %this.setImageTrigger(0,1);
        %this.schedule(100, setImageTrigger, 0, 0);
}
 
function AIPlayer::ThinkNextMove(%this, %dest)
{
        if(isObject(%dest) && (%dest.getClassName $= "fxDTSBrick" || %dest.getClassName $= "PlayerData"))
                %destination = %dest.getPosition();
        else
                %destination = %dest;
        %this.destination = %dest;
        %realism = 10; // Higher = more realistic
        %realismAngles = mFloor(180/%realism);
        %myangle = mRadToDeg(mATan(getWord(%ev=%this.getEyeVector(),1),getWord(%ev,0)));
        for(%i = 0; %i <= %realism; %i++)
        {
                %angle = mDegToRad(%realismAngles * %i);
                %angle = mCos(%angle) * 90;
                %angle += %myangle;
                %x = mCos(mDegToRad(%angle))*2;
                %y = mSin(mDegToRad(%angle))*2;
                %ray = containerRaycast(%this.getEyePoint(), %pos = vectorAdd(%this.getEyePoint(), %x SPC %y SPC -0), $TypeMasks::FxBrickObjectType);
                %dir = vectorAdd(%this.getPosition(), %x SPC %y SPC 0);
                if(isObject(getWord(%ray,0)))
                {
                        //%ray.getID().setColor(%ray.getID().getColorID()+1);
                        continue;
                }
                %dist = vectorDist(%pos, %destination);
                if(%dist < %closest || %closest $= "")
                {
                        %ray = containerRayCast(vectorAdd(%this.getEyePoint(),mCos(mDegToRad(%myAngle)+1.5708) SPC mSin(mDegToRad(%myAngle)+1.5708) SPC 0), %pos, $TypeMasks::FxBrickObjectType);
                        if(isObject(%ray))
                                continue;
                        %ray = containerRayCast(vectorAdd(%this.getEyePoint(),mCos(mDegToRad(%myAngle)-1.5708) SPC mSin(mDegToRad(%myAngle)-1.5708) SPC 0), %pos, $TypeMasks::FxBrickObjectType);
                        if(isObject(%ray))
                                continue;
                        %closest = %dist;
                        %closestpos = %pos;
                        %closestdir = %dir;
                }
        }
        if(%closestpos $= "")
        {
                %myangle -= 180;
                %x = mCos(mDegToRad(%myangle))*3;
                %y = mSin(mDegToRad(%myangle))*3;
                %pos = vectorAdd(%this.getEyePoint(), %x SPC %y SPC 0);
                %closestpos = %pos;
        }
        if(getWord(vectorSub(%this.getPosition(), %destination),2) < -1.5)
        {
                if(%this.getMountedImage(2) != 0)
                        %this.mountImage(BlankImage2,2);
                %this.setImageTrigger(2,1);
                %this.schedule(330,setImageTrigger,2,0);
        }
        //announce(%closestpos);
        //m(%closestpos);
        %this.setMoveDestination(%closestpos,0);
        //%this.setAimLocation(getWords(%closestpos,0,1) SPC getWord(%this.getPosition(),2)+2.1);
        //%this.moveSchedule = %this.schedule(500,ThinkNextMove,%dest);
}
 
function eulerToAxis(%euler)
{
        %euler = VectorScale(%euler,$pi / 180);
        %matrix = MatrixCreateFromEuler(%euler);
        return getWords(%matrix,3,6);
}
 
function axisToEuler(%axis)
{
        %angleOver2 = getWord(%axis,3) * 0.5;
        %angleOver2 = -%angleOver2;
        %sinThetaOver2 = mSin(%angleOver2);
        %cosThetaOver2 = mCos(%angleOver2);
        %q0 = %cosThetaOver2;
        %q1 = getWord(%axis,0) * %sinThetaOver2;
        %q2 = getWord(%axis,1) * %sinThetaOver2;
        %q3 = getWord(%axis,2) * %sinThetaOver2;
        %q0q0 = %q0 * %q0;
        %q1q2 = %q1 * %q2;
        %q0q3 = %q0 * %q3;
        %q1q3 = %q1 * %q3;
        %q0q2 = %q0 * %q2;
        %q2q2 = %q2 * %q2;
        %q2q3 = %q2 * %q3;
        %q0q1 = %q0 * %q1;
        %q3q3 = %q3 * %q3;
        %m13 = 2.0 * (%q1q3 - %q0q2);
        %m21 = 2.0 * (%q1q2 - %q0q3);
        %m22 = 2.0 * %q0q0 - 1.0 + 2.0 * %q2q2;
        %m23 = 2.0 * (%q2q3 + %q0q1);
        %m33 = 2.0 * %q0q0 - 1.0 + 2.0 * %q3q3;
        return mRadToDeg(mAsin(%m23)) SPC mRadToDeg(mAtan(-%m13, %m33)) SPC mRadToDeg(mAtan(-%m21, %m22));
}
 
};
activatepackage(dren);
The first problem is they're not aggressive enough. They'll chase people sometimes, but you usually have to wait a bit.
The second and far worse problem is that it seems to crash, but nothing shows in the console, and it takes far too long to make tracing it a possibility.

Could anyone offer some assistance to at least make this not crash, and maybe make it a bit better?


edit:  I tried leaving trace on, but the console log becomes over 20 megabytes and then bl crashes from a buffer overrun. So yeah, tracing isn't an option.
« Last Edit: February 18, 2013, 02:08:56 PM by DrenDran »

i laughed
so hard.



Try taking it out of a package, and remove your stuff with lights.
« Last Edit: February 18, 2013, 12:35:48 PM by Perlin Noise »

i laughed
so hard.



Try taking it out of a package, and remove your stuff with lights.
Try loving yourself.

Code: [Select]
$numlights
$lightpos[%a]
What

What

Code: [Select]
$numlights
$lightpos[%a]
What

What
Code: [Select]
function compileLights()
{
        if(!isObject($mainbrickgroup))
                $mainbrickgroup = findclientbyname("drendran").brickGroup;
       
        $numlights = 0;
       
        for(%a=0;%a<$mainbrickgroup.getCount();%a++)
        {
                %brick = $mainbrickgroup.getObject(%a);
                if(isObject(%brick))
                {
                        if(isObject(%brick.light))
                        {
                                $lightpos[$numlights] = %brick.position;
                                $numlights++;
                        }
                }
        }
}

Code: [Select]
function compileLights()
{
        if(!isObject($mainbrickgroup))
                $mainbrickgroup = findclientbyname("drendran").brickGroup;
       
        $numlights = 0;
       
        for(%a=0;%a<$mainbrickgroup.getCount();%a++)
        {
                %brick = $mainbrickgroup.getObject(%a);
                if(isObject(%brick))
                {
                        if(isObject(%brick.light))
                        {
                                $lightpos[$numlights] = %brick.position;
                                $numlights++;
                        }
                }
        }
}
mainbrickgroup contains other brickgroups
Not bricks

mainbrickgroup contains other brickgroups
Not bricks
$mainbrickgroup isn't mainBrickGroup
That part works fine, trust me.