Author Topic: Triggering code when a bot is in the line of sight  (Read 2071 times)

I need a looping function that can tell if there's an AIPlayer in the view for my upcoming horror mod. I've tried raycasts, but it won't work properly.

Can anyone tell me how do do this?

While i'm not sure on the code, you could try a bit of math using both the players and the bots positions, the players eyevector, and the players FOV. Im fairly sure that would detect whether the bot is in front of the player, then if it is, just raycast between the bot and the player to detect if anything is blocking the sight. A lot easier said than done though..

While i'm not sure on the code, you could try a bit of math using both the players and the bots positions, the players eyevector, and the players FOV. Im fairly sure that would detect whether the bot is in front of the player, then if it is, just raycast between the bot and the player to detect if anything is blocking the sight. A lot easier said than done though..
But fov is handled client-sided

But fov is handled client-sided
You can assume a 90 degree fov, I believe

Anyways, I would suggest to do exactly as boodals has recommended

I got it working using a straight line raycast but it only triggers when the player looks directly at the bot:
Code: [Select]
function Player::RenderViewLoop(%this) {
    cancel(%this.RenderViewLoop); // get rid of the dupes
    if(!isObject(%this) || !isObject(%this.client))
return;
    %this.RVLoop = %this.schedule(10, "RenderViewLoop");
    %eye = vectorScale(%this.getEyeVector(), 100);
    %pos = %this.getEyePoint();
    %mask = $TypeMasks::PlayerObjectType;
    %hit = firstWord(containerRaycast(%pos, vectorAdd(%pos, %eye), %mask, %this));
    %cl = %this.client;
    if(isObject(%hit)) {
        if(isObject(%lastrendermanhit)) {
            if(%hit == %lastrendermanhit) {
                return;
            }
        }
        if(%hit.getClassName() $= "AIPlayer" && %hit.isRenderman == 1) {
            %lastrendermanhit = %hit;
            %distancetorender = vectordist(%this.getPosition(), %hit.getPosition());
            if(%distancetorender >= 14) { // safe distance?
                // TODO
            } else {
                %this.setdatablock("PlayerFrozenArmor");  // stop the player from moving
                %cl.play2d(RenderDeath);
                %this.RKill = %this.schedule(2000, "renderKick");
            }
        }
    }
}

Oh, I have some code for you. One minute. had to plug in my second harddrive to get it, lol.

Code: [Select]
function Player::canSeeObject(%this, %object)
{
%ev = %this.getEyeVector();
%pos = %this.getPosition();
if(!isObject(%object))
return 0;
%ep = isFunction(%object.getClassname(), getEyePoint) ? %object.getEyePoint() : %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;
}

Then, for the loop:
Code: [Select]
function Player::CanSeeLoop(%this)
{
if(%this.canSeeObject($HorrorObject))
{
whatever();
}
%this.schedule(100,canSeeLoop);
}
« Last Edit: November 24, 2012, 04:48:00 PM by Trinick »

Oh, I have some code for you. One minute. had to plug in my second harddrive to get it, lol.

- awsomeness snip-
Thanks!

I'm actually pretty proud of that code. I have a very rough understanding of trigonometry yet I got that to work flawlessly in under 15 minutes when I wrote it.

Oh, I have some code for you. One minute. had to plug in my second harddrive to get it, lol.
There are a few issues with that code. For one, it only tries to hit bricks, even though other players, static shapes, vehicles, etc. might be in the way. It assumes that if an object is hit by the raycast the target object must not be in view, even though the object it hit may even be the target object (understandable because you assumed it would only hit bricks, but it would be nice to change the example code to work for other types). Finally, it would be nice if you made a variable for the field of view, as I can imagine whatever fixed amount you have currently is not going to be perfect for all use cases.

Of course, even then it won't be perfect. I made this code a year ago but it is also flawed; you need to do a lot more checking for it to be perfect (like scaling the size of the object by inversed distance to see how visible it is from that point in comparison to objects hit by the raycast).
« Last Edit: November 25, 2012, 05:21:41 AM by Destiny/Zack0Wack0 »

Obviously it's impractical to say the least to check if any piece of the player is visible, so instead this checks for an individual spot, which you know.

I highly doubt players will have a modified FoV, it's not impractical at all to assume a default of 90 degrees.

Also, I have it only check for bricks because those are the only static things that will realistically block view. Players/bots move, and even if they don't, more than likely part of the bot is exposed so this acts as a partial improvement to that issue.

I see no issues with my code.

I would use "good enough" to describe slick's code. I'm doubtful that OP will need any of those changes, he mentioned using it for a creepy AI or something similar

You could probably make it more appropriate for your purposes if it checked whether you can see the bot's head instead of just using getPosition. If you called it in reverse, too, you would be checking to see if the player can actually see the bot's face.

You could probably make it more appropriate for your purposes if it checked whether you can see the bot's head instead of just using getPosition. If you called it in reverse, too, you would be checking to see if the player can actually see the bot's face.
It already does that.

It already does that.
Oh, I see. Overlooked that eyepoint bit when reading it.

-snip-
How could I make this work for bots seeing players?