yay for type checking (I think). now the bots are /really/ screwed :(

This commit is contained in:
Bill Currie 2003-08-22 06:35:19 +00:00
parent c45e996252
commit f4f6e897b3
6 changed files with 238 additions and 218 deletions

View file

@ -144,14 +144,14 @@ Bot has lost its target.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
*/
-(void)lost:(Waypoint)targ :(integer)success
-(void)lost:(Target)targ :(integer)success
{
if (!targ)
return;
[self targetDrop:targ];
if (targ.ent.classname == "waypoint")
targ.b_sound &= ~b_clientflag;
if ([targ isKindOfClass:[Waypoint class]])
((Waypoint)targ).b_sound &= ~b_clientflag;
// find a new route
if (!success) {
@ -174,8 +174,8 @@ Bot has lost its target.
}
}
if (targ.ent.classname != "player")
targ.search_time = time + 5;
//XXX if (targ.ent.classname != "player")
//XXX targ.search_time = time + 5;
}
/*
@ -188,7 +188,7 @@ removed.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
*/
-(void)checkLost:(Waypoint)targ
-(void)checkLost:(Target)targ
{
local vector dist;
@ -199,65 +199,71 @@ removed.
dist_z = 0;
// waypoints and items are lost if you get close enough to them
if (targ.ent.flags & FL_ITEM) {
if (vlen (targ.ent.origin - ent.origin) < 32)
[self lost:targ :TRUE];
else if (!targ.ent.model)
[self lost:targ :TRUE];
} else if (targ.ent.classname == "waypoint") {
if ([targ isKindOfClass:[Waypoint class]]) {
local Waypoint way = (Waypoint) targ;
if (!(b_aiflags & (AI_SNIPER | AI_AMBUSH))) {
if (b_aiflags & AI_RIDE_TRAIN) {
if (vlen (targ.origin - ent.origin) < 48)
[self lost:targ :TRUE];
if (vlen (way.origin - ent.origin) < 48)
[self lost:way :TRUE];
} else if (b_aiflags & AI_PRECISION) {
if (vlen (targ.origin - ent.origin) < 24)
[self lost:targ :TRUE];
} else if (vlen (targ.origin - ent.origin) < 32)
[self lost:targ :TRUE];
if (vlen (way.origin - ent.origin) < 24)
[self lost:way :TRUE];
} else if (vlen (way.origin - ent.origin) < 32)
[self lost:way :TRUE];
}
} else if (targ.ent.classname == "temp_waypoint") {
if (vlen (targ.origin - ent.origin) < 32)
[self lost:targ :TRUE];
} else if (targ.ent.classname == "player") {
if (targ.ent.health <= 0)
[self lost:targ :TRUE];
else if ((coop) || (teamplay && targ.ent.team == ent.team)) {
if (targ.targets[0].ent.classname == "player") {
if (![targ.targets[0] ishuman])
[self lost:targ :TRUE];
} else if (targ.ent.teleport_time > time) {
//temp_waypoint
if (vlen (way.origin - ent.origin) < 32)
[self lost:way :TRUE];
} else if ([targ isKindOfClass:[Bot class]]) {
local Bot bot = (Bot) targ;
if (bot.ent.health <= 0)
[self lost:bot :TRUE];
else if ((coop) || (teamplay && bot.ent.team == ent.team)) {
if (bot.targets[0].ent.classname == "player") {
if (![bot.targets[0] ishuman])
[self lost:bot :TRUE];
} else if (bot.ent.teleport_time > time) {
// try not to telefrag teammates
keys &= ~KEY_MOVE;
} else if (vlen (targ.origin - ent.origin) < 128) {
if (vlen (targ.origin - ent.origin) < 48)
[self walkmove: ent.origin - targ.origin];
} else if (vlen (bot.ent.origin - ent.origin) < 128) {
if (vlen (bot.ent.origin - ent.origin) < 48)
[self walkmove: ent.origin - bot.ent.origin];
else {
keys &= ~KEY_MOVE;
[self startTopic:4];
}
ent.search_time = time + 5; // never time out
} else if (![self canSee:targ])
[self lost:targ :FALSE];
} else if (![self canSee:bot])
[self lost:bot :FALSE];
} else if (waypoint_mode > WM_LOADED) {
if (vlen (targ.origin - ent.origin) < 128) {
[self lost:targ :TRUE];
if (vlen (bot.ent.origin - ent.origin) < 128) {
[self lost:bot :TRUE];
}
}
} else if (targ.ent.classname == "func_button") {
// buttons are lost of their frame changes
if (targ.ent.frame) {
[self lost:targ :TRUE];
if (ent.enemy == targ.ent)
ent.enemy = NIL;
// if (target[0])
// [self getPath:target[0] :TRUE];
}
} else if ((targ.ent.movetype == MOVETYPE_NONE) && (targ.ent.solid == SOLID_TRIGGER)) {
// trigger_multiple style triggers are lost if their thinktime changes
if (targ.ent.nextthink >= time) {
[self lost:targ :TRUE];
// if (target[0])
// [self getPath:target[0] :TRUE];
} else {
if (targ.ent.flags & FL_ITEM) {
if (vlen (targ.ent.origin - ent.origin) < 32)
[self lost:targ :TRUE];
else if (!targ.ent.model)
[self lost:targ :TRUE];
} else if (targ.ent.classname == "func_button") {
// buttons are lost of their frame changes
if (targ.ent.frame) {
[self lost:targ :TRUE];
if (ent.enemy == targ.ent)
ent.enemy = NIL;
// if (target[0])
// [self getPath:target[0] :TRUE];
}
} else if ((targ.ent.movetype == MOVETYPE_NONE)
&& (targ.ent.solid == SOLID_TRIGGER)) {
// trigger_multiple style triggers are lost if their thinktime
// changes
if (targ.ent.nextthink >= time) {
[self lost:targ :TRUE];
// if (target[0])
// [self getPath:target[0] :TRUE];
}
}
}
// lose any target way above the bot's head
@ -512,99 +518,49 @@ the bot finds things it wants to kill/grab.
// *!* Make sure you add code to checkLost to remove the target *!*
-(float)priorityForThing:(Target)thing
-(integer)priority:(Bot)bot
{
local float thisp;
local integer p;
thisp = 0;
// This is the most executed function in the bot. Careful what you do here.
if ((thing.flags & FL_ITEM) && thing.model && thing.search_time < time) {
// ugly hack
//XXX if (thing._last != ent)
//XXX thisp = 20;
if (thing.classname == "item_artifact_super_damage")
thisp = 65;
else if (thing.classname == "item_artifact_invulnerability")
thisp = 65;
else if (thing.classname == "item_health") {
if (thing.spawnflags & 2)
thisp = 55;
if (ent.health < 40)
thisp = thisp + 50;
} else if (thing.model == "progs/armor.mdl") {
if (ent.armorvalue < 200) {
if (thing.skin == 2)
thisp = 60;
else if (ent.armorvalue < 100)
thisp = thisp + 25;
}
} else if (thing.classname == "weapon_supershotgun") {
if (!(ent.items & IT_SUPER_SHOTGUN))
thisp = 25;
} else if (thing.classname == "weapon_nailgun") {
if (!(ent.items & IT_NAILGUN))
thisp = 30;
} else if (thing.classname == "weapon_supernailgun") {
if (!(ent.items & IT_SUPER_NAILGUN))
thisp = 35;
} else if (thing.classname == "weapon_grenadelauncher") {
if (!(ent.items & IT_GRENADE_LAUNCHER))
thisp = 45;
} else if (thing.classname == "weapon_rocketlauncher") {
if (!(ent.items & IT_ROCKET_LAUNCHER))
thisp = 60;
} else if (thing.classname == "weapon_lightning") {
if (!(ent.items & IT_LIGHTNING))
thisp = 50;
}
} else if ((thing.flags & FL_MONSTER) && thing.health > 0)
thisp = 45;
else if (thing.classname == "player") {
if (thing.health > 0) {
if (thing == ent)
return 0;
else {
if (thing.items & IT_INVISIBILITY) //FIXME
thisp = 2;
else if (coop) {
thisp = 100;
//XXX if (thing.targets[0].classname == "player")
//XXX if (!thing.targets[0].ishuman)
//XXX return 0;
} else if (teamplay && thing.team == ent.team) {
thisp = 100;
//XXX if (thing.targets[0].classname == "player")
//XXX return 0;
} else
thisp = 30;
}
}
} else if (thing.classname == "waypoint") {
//XXX if (thing.b_aiflags & AI_SNIPER)
//XXX thisp = 30;
//XXX else if (thing.b_aiflags & AI_AMBUSH)
//XXX thisp = 30;
}
if (pointcontents (thing.origin) < -3)
if (ent.health <= 0)
return 0;
if (thisp) {
/*XXX
if (thing.current_way) {
// check to see if it's unreachable
if (thing.current_way.items == -1)
if (ent.items & IT_INVISIBILITY) //FIXME
p = 2;
else if (coop) {
if (targets[0].ent.classname == "player")
if (![targets[0] ishuman])
return 0;
else
thisp += (13000 - thing.current_way.items) * 0.05;
}
*/
}
return thisp;
p = 100;
} else if (teamplay && ent.team == bot.ent.team) {
if (targets[0].ent.classname == "player")
return 0;
p = 100;
} else
p = 30;
if (current_way) {
// check to see if it's unreachable
if (current_way.items == -1)
return 0;
else
p += (integer) ((13000 - current_way.items) * 0.05);
}
return p;
}
-(integer)priorityForThing:(Target)thing
{
// This is the most executed function in the bot. Careful what you do here.
if (pointcontents ([thing origin]) < -3)
return 0;
return [thing priority:self];
}
-(void)lookForCrap:(integer)scope
{
local Target foe, best = NIL;
local float thatp, bestp, dist;
local integer thatp, bestp;
local float dist;
if (scope == 1)
foe = [Target forEntity:findradius (ent.origin, 13000)];

View file

@ -77,9 +77,10 @@ weapon_range =
};
@implementation Bot (Fight)
-(float)sizePlayer:(entity)e
-(float)sizePlayer:(Target)targ
{
local float sz;
local entity e = targ.ent;
sz = e.health + e.armorvalue * e.armortype;
switch (e.weapon) {
@ -134,7 +135,7 @@ weapon_range =
if (ent.enemy) {
v = ent.origin - realorigin (ent.enemy);
foedist = vlen (v);
foesz = [self sizePlayer:ent.enemy];
foesz = [self sizePlayer:[Target forEntity:ent.enemy]];
} else {
foedist = 3000;
foesz = 9999999;
@ -184,9 +185,10 @@ weapon_range =
if (foe.health > 0) {
flen = vlen (foe.origin - ent.origin);
if (flen < foedist) {
tsz = [self sizePlayer:foe];
local Target targ = [Target forEntity:foe];
tsz = [self sizePlayer:targ];
if (tsz < foesz) {
if ([self canSee:foe]) {
if ([self canSee:targ]) {
ent.enemy = foe;
foedist = flen;
foesz = tsz;
@ -316,7 +318,7 @@ attacking an enemy.
} else if (!ent.enemy.takedamage) {
ent.enemy = NIL;
return;
} else if (![self canSee:ent.enemy]) {
} else if (![self canSee:[Target forEntity:ent.enemy]]) {
ent.enemy = NIL;
return;
}
@ -340,7 +342,7 @@ attacking an enemy.
[self weaponSwitch:foedist];
if (!(b_aiflags & (AI_PRECISION | AI_BLIND | AI_OBSTRUCTED))) {
foesz = [self sizePlayer:ent.enemy];
foesz = [self sizePlayer:[Target forEntity:ent.enemy]];
mysz = [self sizePlayer:self] + 5;
if (foesz > mysz) {
@ -378,7 +380,7 @@ attacking an enemy.
[self walkmove:v_right * -1];
}
} else {
foesz = [self sizePlayer:ent.enemy];
foesz = [self sizePlayer:[Target forEntity:ent.enemy]];
mysz = [self sizePlayer:self] + 5;
if (foesz > mysz)

View file

@ -50,49 +50,6 @@ integer bot_way_linker;
@implementation Bot (Way)
/*
FindWaypoint
This is used quite a bit, by many different
functions big lag causer
Finds the closest, fisible, waypoint to e
*/
-(Waypoint)findWaypoint:(Waypoint)start
{
local Waypoint best, t;
local float dst, tdst;
local vector org;
local integer count, i;
org = realorigin (ent);
if (start) {
dst = vlen (start.origin - org);
best = start;
} else {
dst = 100000;
best = NIL;
}
count = [waypoint_array count];
for (i = 0; i < count; i++) {
t = [waypoint_array getItemAt:i];
// real players cut through ignore types
if (dst < 20)
return best;
if (!(t.flags & AI_IGNORE_TYPES) || ishuman) {
tdst = vlen (t.origin - org);
if (tdst < dst) {
if (sisible (ent, t.ent)) {
dst = tdst;
best = t;
}
}
}
}
return best;
}
-(void)deleteWaypoint:(Waypoint)what
{
if (current_way == what)
@ -181,19 +138,18 @@ different bot.
*/
-(void)markPath:(entity)this
-(void)markPath:(Target)this
{
local Waypoint t;
local integer flag;
local Bot bot = (Bot)this.@this;
[Waypoint clearMyRoute:self];
t = [this.@this findWaypoint:bot.current_way];
t = [this findWaypoint:this.current_way];
// FIXME
// ugh, better way to find players please!!!
if (this.classname != "player")
bot.current_way = t;
if (this.ent.classname != "player")
this.current_way = t;
if (t.enemy == NIL) {
[self lost:this :FALSE];
@ -260,7 +216,7 @@ Boy it's confusing.
}
}
-(void)getPath:(Waypoint)this :(integer)direct
-(void)getPath:(Target)this :(integer)direct
{
if (this == NIL)
return;
@ -389,8 +345,8 @@ very good all things considered.
local integer i;
for (i = 0; i < 4; i++) {
if (way.targets[i]) {
DeveloperLightning (way, way.targets[i],
if (way.links[i]) {
DeveloperLightning (way, way.links[i],
way.flags & (AI_TELELINK_1 << i));
}
}

View file

@ -11,6 +11,8 @@ typedef struct bot_data_t bot_data_t;
@interface Target: Entity
{
@public
Waypoint current_way;
}
+(Target)forEntity:(entity)ent;
-(vector)realorigin;
@ -19,12 +21,14 @@ typedef struct bot_data_t bot_data_t;
-(void)setOrigin:(vector) org;
-(integer)recognizePlat:(integer)flag;
-(integer)ishuman;
-(integer)priority:(Bot)bot;
-(Waypoint)findWaypoint:(Waypoint)start;
@end
@interface Waypoint: Target
{
@public
Waypoint [4] targets;
Waypoint [4] links;
integer flags;
vector origin;
@ -97,7 +101,6 @@ typedef struct bot_data_t bot_data_t;
float dyn_time;
Waypoint temp_way;
Waypoint last_way;
Waypoint current_way;
Target [4] targets;
entity avoid;
vector obs_dir;
@ -148,18 +151,18 @@ typedef struct bot_data_t bot_data_t;
-(integer)targetOnstack:(Target)scot;
-(void)targetAdd:(Target)e;
-(void)targetDrop:(Target)e;
-(void)lost:(Waypoint)targ :(integer)success;
-(void)checkLost:(Waypoint)targ;
-(void)lost:(Target)targ :(integer)success;
-(void)checkLost:(Target)targ;
-(void)handleAI;
-(void)path;
-(float)priorityForThing:(Target)thing;
-(void)lookForCrap:(integer)scope;
-(void)angleSet;
-(void)AI;
-(integer)priorityForThing:(Target)thing;
@end
@interface Bot (Fight)
-(float)sizePlayer:(entity)e;
-(float)sizePlayer:(Target)targ;
-(void)dodgeStuff;
-(void)weaponSwitch:(float)brange;
-(void)shoot;
@ -167,12 +170,11 @@ typedef struct bot_data_t bot_data_t;
@end
@interface Bot (Way)
-(Waypoint)findWaypoint:(Waypoint)start;
-(void)deleteWaypoint:(Waypoint)what;
-(entity)findThing:(string)s;
-(Waypoint)findRoute:(Waypoint)lastone;
-(void)markPath:(entity)this;
-(void)getPath:(Waypoint)this :(integer)direct;
-(void)markPath:(Target)this;
-(void)getPath:(Target)this :(integer)direct;
-(integer)beginRoute;
-(void)spawnTempWaypoint:(vector)org;
-(void)dynamicWaypoint;

View file

@ -73,6 +73,9 @@ struct target_s = {
local Target t;
local struct target_s ele;
if (!ent)
return NIL;
if (ent.classname == "player")
return ent.@this;
@ -138,4 +141,95 @@ struct target_s = {
return 0;
}
-(integer)priority:(Bot)bot
{
if ((ent.flags & FL_ITEM) && ent.model && ent.search_time < time) {
// ugly hack
//XXX if (ent._last != bot)
//XXX thisp = 20;
if (ent.classname == "item_artifact_super_damage")
return 65;
else if (ent.classname == "item_artifact_invulnerability")
return 65;
else if (ent.classname == "item_health") {
if (ent.spawnflags & 2)
return 55;
if (bot.ent.health < 40)
return 55 + 50;
} else if (ent.model == "progs/armor.mdl") {
if (bot.ent.armorvalue < 200) {
if (ent.skin == 2)
return 60;
else if (bot.ent.armorvalue < 100)
return 60 + 25;
}
} else if (ent.classname == "weapon_supershotgun") {
if (!(bot.ent.items & IT_SUPER_SHOTGUN))
return 25;
} else if (ent.classname == "weapon_nailgun") {
if (!(bot.ent.items & IT_NAILGUN))
return 30;
} else if (ent.classname == "weapon_supernailgun") {
if (!(bot.ent.items & IT_SUPER_NAILGUN))
return 35;
} else if (ent.classname == "weapon_grenadelauncher") {
if (!(bot.ent.items & IT_GRENADE_LAUNCHER))
return 45;
} else if (ent.classname == "weapon_rocketlauncher") {
if (!(bot.ent.items & IT_ROCKET_LAUNCHER))
return 60;
} else if (ent.classname == "weapon_lightning") {
if (!(bot.ent.items & IT_LIGHTNING))
return 50;
}
} else if ((ent.flags & FL_MONSTER) && ent.health > 0)
return 45;
return 0;
}
/*
FindWaypoint
This is used quite a bit, by many different
functions big lag causer
Finds the closest, fisible, waypoint to e
*/
-(Waypoint)findWaypoint:(Waypoint)start
{
local Waypoint best, t;
local float dst, tdst;
local vector org;
local integer count, i;
local integer ishuman = [self ishuman];
org = [self realorigin];
if (start) {
dst = vlen ([start origin] - org);
best = start;
} else {
dst = 100000;
best = NIL;
}
count = [waypoint_array count];
for (i = 0; i < count; i++) {
t = [waypoint_array getItemAt:i];
// real players cut through ignore types
if (dst < 20)
return best;
if (!(t.flags & AI_IGNORE_TYPES) || ishuman) {
tdst = vlen (t.origin - org);
if (tdst < dst) {
traceline (ent.origin, t.origin, TRUE, ent);
if (trace_fraction == 1) {
dst = tdst;
best = t;
}
}
}
}
return best;
}
@end

View file

@ -56,6 +56,7 @@ Array waypoint_array;
{
if (!waypoint_array) {
waypoint_array = [[Array alloc] init];
[waypoint_array addItem:NIL];
waypoint_queue = [[List alloc] init];
waypoint_thinker = spawn ();
waypoint_thinker.classname = "waypoint_thinker";
@ -121,7 +122,7 @@ make_waypoint =
return 0;
for (i = 0; i < 4; i++) {
if (targets[i] == way) {
if (links[i] == way) {
if (flags & (AI_TELELINK_1 << i))
return 2;
return 1;
@ -140,8 +141,8 @@ make_waypoint =
return 0; // already linked!!!
for (i = 0; i < 4; i++) {
if (!targets[i]) {
targets[i] = way;
if (!links[i]) {
links[i] = way;
return 1;
}
}
@ -159,8 +160,8 @@ make_waypoint =
return 0; // already linked!!!
for (i = 0; i < 4; i++) {
if (!targets[i]) {
targets[i] = way;
if (!links[i]) {
links[i] = way;
flags |= AI_TELELINK_1 << i;
return 1;
}
@ -178,9 +179,9 @@ make_waypoint =
return;
for (i = 0; i < 4; i++) {
if (targets[i] == way) {
if (links[i] == way) {
flags &= ~(AI_TELELINK_1 << i);
targets[i] = NIL;
links[i] = NIL;
}
}
}
@ -207,10 +208,10 @@ Waypoint Loading from file
-(void)fix
{
targets[0] = [Waypoint waypointForNum:b_pants];
targets[1] = [Waypoint waypointForNum:b_skill];
targets[2] = [Waypoint waypointForNum:b_shirt];
targets[3] = [Waypoint waypointForNum:b_frags];
links[0] = [Waypoint waypointForNum:b_pants];
links[1] = [Waypoint waypointForNum:b_skill];
links[2] = [Waypoint waypointForNum:b_shirt];
links[3] = [Waypoint waypointForNum:b_frags];
}
+(void) fixWaypoints
@ -301,16 +302,16 @@ tripping the runaway loop counter
// can you say ugly?
if (flags & AI_TRACE_TEST) {
for (i = 0; i < 4; i++) {
if (targets[i]) {
traceline (origin, targets[i].origin, TRUE, /*self*/NIL);
if (links[i]) {
traceline (origin, links[i].origin, TRUE, /*self*/NIL);
if (trace_fraction == 1)
[self followLink:targets[i].origin :AI_TELELINK_1 << i];
[self followLink:links[i] :AI_TELELINK_1 << i];
}
}
} else {
for (i = 0; i < 4; i++) {
if (targets[i]) {
[self followLink:targets[i].origin :AI_TELELINK_1 << i];
if (links[i]) {
[self followLink:links[i] :AI_TELELINK_1 << i];
}
}
}
@ -345,6 +346,15 @@ tripping the runaway loop counter
return self;
}
-(integer)priority:(Bot)bot
{
if (flags & AI_SNIPER)
return 30;
else if (flags & AI_AMBUSH)
return 30;
return 0;
}
@end