# Forum

## CantSee () Function

Discuss Artificial Intelligence and Bot programming.

### CantSee () Function

I made this new code, check it out and post feedback.

More or less Im using it as an advanced replacement for Visible () , or Fisible () in my Frikbot code, but have not implimented it yet completely. It does seem to more or less work in cases where the target is completely not
visible. I had noticed that on DM2 For example, Frikbot would fire at you if you were partialy visible through one of the slotted horizontal bars forming the map near the Rocket Lanucher area and wall buttons. Apparently
it could see the target but the aim was never hitting using the Shotgun. I dont know if it was because of the bots skill, so I set out trying to get a better calculation for its aim. I suppose from here we could actually reference all 16 points
as .vectors then aim at either an individual offset or do another calc based on the groups that are hit.

Also, it might have some uses calculating a possible headshot?

Code: Select all
float(entity from, entity seen) CantSee =
{
local float score;
local vector start;
if (self.ishuman == 1)
makevectors (from.v_angle);
else
makevectors2 (from.angles);

score = 100;

start = realorigin(from) + from.view_ofs + v_forward*18;

// Bottom corners
traceline (start, (seen.absmin), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

traceline (start, (seen.absmax - '0 0 56'), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

traceline (start, (seen.absmax - '0 32 56'), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

traceline (start, (seen.absmax - '0 -32 0'), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

// Bottom sides

traceline (start, (realorigin(seen) + '0 -16 -22'), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

traceline (start, (realorigin(seen) + '0 16 -22'), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

traceline (start, (realorigin(seen) + '16 0 -22'), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

traceline (start, (realorigin(seen) + '-16 0 -22'), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

// Top corners
traceline (start, (seen.absmin + '0 0 56'), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

traceline (start, (seen.absmax), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

traceline (start, (seen.absmax - '0 32 0'), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

traceline (start, (seen.absmin - '0 -32 -56'), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

// Top sides
traceline (start, (realorigin(seen) + '0 -16 32'), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

traceline (start, (realorigin(seen) + '0 16 32'), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

traceline (start, (realorigin(seen) + '16 0 32'), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

traceline (start, (realorigin(seen) + '-16 0 32'), FALSE, seen);
if (trace_fraction < 1)
score = score - 6.25;

// Skip this one for now
/*
// bottom center
traceline (self.origin + self.view_ofs, (here), FALSE, self);
if (trace_fraction < 1)
score = score + 1;

*/

//if (score == 16) return 1;

return score;
};

Cobalt

Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA

### Re: CantSee () Function

What engine are you using ? This looks like a poor-man's tracebox(), which already exists on FTE and Darkplaces (and, IIRC FrikBot's sources, is already emulated somewhere else).
If you're using any other engine, it may be worth the effort to implement the builtin (or ask someone to do this).
Also, after all the hassle of firing a lot of tracelines, you are discarding important stuff that could be useful if you have locational damage in your mod.

I'd suggest the following:

a) IMHO the function name is a bit misleading. By default, the bot "can't see" the enemies. VisibleBodyParts() would be a more clear description;
b) the function return could simply a float encoded with bits signaling what parts of the body (head, torso, legs) are "clear shots" so the AI can decide if is worth to try a shot with the current weapon or not;
c) You can even give different weights for different body parts (ex: head = 4, torso = 2, legs = 1), therefore you could quickly decide if a headshot is viable:
Code: Select all
if (VisibleBodyParts() > 3) { headshot = TRUE; }  // gotcha!
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC (LordHavoc)

frag.machine

Posts: 2120
Joined: Sat Nov 25, 2006 1:49 pm

### Re: CantSee () Function

tracebox is often not viable for detecting visibility. it basically means that a player can hide slightly behind a corner and the box will always hit the wall instead of the player, making them invisible yet still able to hit the bot.
really, visibility needs an inverted bbox of sorts, but engines don't support this (there's not enough overlap in q3bsp for it to be practical there, either).
(engine-wise, tracebox is trivial to implement, all the functionality is already there, you just need to make a new version of the traceline builtin that actually passes the sizes through, instead of '0 0 0')

you should instead track which part of the player's bbox you *can* see, and aim at that instead of directly at their origin. normally it doesn't matter which part of their bbox you hit, so long as you can actually do some damage (rockets should normally be aimed at the feet, for instance, so you can get splashdamage even if you otherwise miss).

presumably you'll also want to use the aiming point rather than the actual eye position, just to guarentee that you don't hit walls (quakeworld clients added a v_viewheight cvar which is normally set to -6 (view=+22, gun=+16, difference is -6), so this is fair game in such a context, and even if it is slightly cheating the simplification means you can justify it in your ai). the origin of guns does not include any forward component either, so just pretend the eye is at origin + '0 0 16', the same point as the gun.
shooting rockets though tiny gaps is always funny, and will help a little with the holes on the floor on dm4 (for example, unintended rocket jumps otherwise). the bars on dm2 won't be affected too much as they're vertical anyway.
Spike

Posts: 2911
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

### Re: CantSee () Function

Engine is DP. Yes, Im aware or Tracebox, but like Spike says, this is not the same. I am tracing lines to the target in the T_damage finction just after the targs health <=0 and calling this function to get a % score. So far it seems to line up with about what you can see of the enemy when you kill it, except of cource the view_oft of 3rd person view can factor in some innacurate calcs, as I am more or less tracing from eye level of the client.

Yea, I originally had it named "Cansee" but I could probably name it PercentSee or PCT_Visible I suppose.

The hard coded vector offsets you see could be misleading and be why you are thinking tracebox. Basicly those are (16) hard coded points on the targets hitbox with respect to its absmin and absmax values that pick corners and sides of the hitbox....and as we tracline to each one we deduct from the overall score of 100 when the traceline hits something , ignoring of course the target.

frag.machine wrote:What engine are you using ? This looks like a poor-man's tracebox(), which already exists on FTE and Darkplaces (and, IIRC FrikBot's sources, is already emulated somewhere else).
If you're using any other engine, it may be worth the effort to implement the builtin (or ask someone to do this).
Also, after all the hassle of firing a lot of tracelines, you are discarding important stuff that could be useful if you have locational damage in your mod.

I'd suggest the following:

a) IMHO the function name is a bit misleading. By default, the bot "can't see" the enemies. VisibleBodyParts() would be a more clear description;
b) the function return could simply a float encoded with bits signaling what parts of the body (head, torso, legs) are "clear shots" so the AI can decide if is worth to try a shot with the current weapon or not;
c) You can even give different weights for different body parts (ex: head = 4, torso = 2, legs = 1), therefore you could quickly decide if a headshot is viable:
Code: Select all
if (VisibleBodyParts() > 3) { headshot = TRUE; }  // gotcha!

Cobalt

Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA

### Re: CantSee () Function

Most are except these. Im also thinking of some custom made maps like used in Lightning Hunters Ultimate Frikbot mappack that may have horizontal jailbars. They are rare though.

[img]
http://i.imgur.com/VBVQbCA.jpg
[/img]

Spike wrote: the bars on dm2 won't be affected too much as they're vertical anyway.

Cobalt

Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA