game-source/fbxa/bot_fight.qc

392 lines
8.5 KiB
C++
Raw Normal View History

/***********************************************
* *
* FrikBot Fight Code *
* "Because I ain't no Ghandi code" *
* *
***********************************************/
/*
This program is in the Public Domain. My crack legal
team would like to add:
RYAN "FRIKAC" SMITH IS PROVIDING THIS SOFTWARE "AS IS"
AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE
ACCURACY, CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR
FUNCTIONING OF THIS SOFTWARE AND/OR DOCUMENTATION. IN
NO EVENT WILL RYAN "FRIKAC" SMITH BE LIABLE FOR ANY
GENERAL, CONSEQUENTIAL, INDIRECT, INCIDENTAL,
EXEMPLARY, OR SPECIAL DAMAGES, EVEN IF RYAN "FRIKAC"
SMITH HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES, IRRESPECTIVE OF THE CAUSE OF SUCH DAMAGES.
You accept this software on the condition that you
indemnify and hold harmless Ryan "FrikaC" Smith from
any and all liability or damages to third parties,
including attorney fees, court costs, and other
related costs and expenses, arising out of your use
of this software irrespective of the cause of said
liability.
The export from the United States or the subsequent
reexport of this software is subject to compliance
with United States export control and munitions
control restrictions. You agree that in the event you
seek to export this software, you assume full
responsibility for obtaining all necessary export
licenses and approvals and for assuring compliance
with applicable reexport restrictions.
Any reproduction of this software must contain
this notice in its entirety.
*/
#include "libfrikbot.h"
2003-07-23 22:44:15 +00:00
/*
weapon_range
_x "sweet spot range" - try to maintain this range if possible
_y minimum range bot can be to be effective (rl/gl) (move away)
_z maximum range bot can be to be effective (lg/axe) (move in)
*/
vector (float wep)
weapon_range =
{
switch (wep) {
case IT_AXE:
2003-07-23 22:44:15 +00:00
return '48 0 64';
case IT_SHOTGUN:
2003-07-23 22:44:15 +00:00
return '128 0 99999';
case IT_SUPER_SHOTGUN:
2003-07-23 22:44:15 +00:00
return '128 0 99999';
case IT_NAILGUN:
2003-07-23 22:44:15 +00:00
return '180 0 3000';
case IT_SUPER_NAILGUN:
2003-07-23 22:44:15 +00:00
return '180 0 3000';
case IT_GRENADE_LAUNCHER:
2003-07-23 22:44:15 +00:00
return '180 48 3000';
case IT_ROCKET_LAUNCHER:
2003-07-23 22:44:15 +00:00
return '180 48 3000';
case IT_LIGHTNING:
2003-07-23 22:44:15 +00:00
return '350 0 512';
default:
break;
}
};
2003-07-23 22:44:15 +00:00
@implementation Bot (Fight)
-(float)size_player:(entity)e
{
local float sz;
sz = e.health + e.armorvalue * e.armortype;
switch (e.weapon) {
case IT_AXE:
sz -= 50;
break;
case IT_LIGHTNING:
sz += 60;
break;
case IT_ROCKET_LAUNCHER:
sz += 60;
break;
case IT_GRENADE_LAUNCHER:
sz += 50;
break;
case IT_SUPER_NAILGUN:
sz += 50;
break;
case IT_NAILGUN:
sz += 40;
break;
case IT_SUPER_SHOTGUN:
sz += 40;
break;
case IT_SHOTGUN:
sz += 10;
break;
default:
break;
}
if (e.items & IT_QUAD)
sz += 200;
if (e.items & IT_INVULNERABILITY)
sz += 300;
if (e.items & IT_INVISIBILITY)
sz += 250;
return sz;
2003-07-23 22:44:15 +00:00
}
2003-07-23 22:44:15 +00:00
-(void)dodge_stuff
{
local entity foe;
local float foedist, avdist, foesz, flen, tsz;
local vector v;
if (waypoint_mode > WM_LOADED)
return;
2003-07-30 16:53:57 +00:00
avoid = NIL;
2003-07-23 22:44:15 +00:00
if (ent.enemy) {
v = ent.origin - realorigin (ent.enemy);
foedist = vlen (v);
2003-07-23 22:44:15 +00:00
foesz = [self size_player:ent.enemy];
2003-03-04 18:26:17 +00:00
} else {
foedist = 3000;
foesz = 9999999;
}
avdist = 256;
foe = find (NIL, classname, "grenade");
while (foe) {
2003-07-23 22:44:15 +00:00
flen = vlen (foe.origin - ent.origin);
2003-03-04 18:26:17 +00:00
if (flen < avdist) {
avdist = flen;
2003-07-30 16:53:57 +00:00
avoid = foe;
}
foe = find (foe, classname, "grenade");
}
2003-07-30 16:53:57 +00:00
if (!avoid) {
foe = find (NIL, classname, "missile");
while (foe) {
2003-07-23 22:44:15 +00:00
if (foe.owner != ent) {
flen = vlen (foe.origin - ent.origin);
2003-03-04 18:26:17 +00:00
if (flen < avdist) {
avdist = flen;
2003-07-30 16:53:57 +00:00
avoid = foe;
}
}
foe = find(foe, classname, "missile");
}
2003-07-30 16:53:57 +00:00
if (!avoid) {
foe = find(NIL, classname, "spike");
while (foe) {
2003-07-23 22:44:15 +00:00
if (foe.owner != ent) {
flen = vlen(foe.origin - ent.origin);
2003-03-04 18:26:17 +00:00
if (flen < avdist) {
avdist = flen;
2003-07-30 16:53:57 +00:00
avoid = foe;
}
}
foe = find (foe, classname, "spike");
}
}
}
2003-03-04 18:26:17 +00:00
if (coop) {
2003-07-23 22:44:15 +00:00
if (!ent.enemy) {
foe = findradius (ent.origin, foedist);
while (foe) {
if (foe.flags & FL_MONSTER) {
if (foe.health > 0) {
2003-07-23 22:44:15 +00:00
flen = vlen (foe.origin - ent.origin);
2003-03-04 18:26:17 +00:00
if (flen < foedist) {
2003-07-23 22:44:15 +00:00
tsz = [self size_player:foe];
2003-03-04 18:26:17 +00:00
if (tsz < foesz) {
if ([self canSee:foe]) {
2003-07-23 22:44:15 +00:00
ent.enemy = foe;
foedist = flen;
foesz = tsz;
}
}
}
}
}
foe = foe.chain;
}
}
2003-03-04 18:26:17 +00:00
} else {
local integer i = 0;
local Bot foe;
for (i = 0; i < 32; i++) {
if (!(foe = players[i]))
continue;
if(foe != self) {
if (foe.ent.modelindex != 0) {
if (foe.ent.health > 0) {
if (!(teamplay && ent.team == foe.ent.team)) {
flen = vlen (foe.ent.origin - ent.origin);
2003-03-04 18:26:17 +00:00
if (flen < foedist) {
2003-07-23 22:44:15 +00:00
tsz = [self size_player:foe];
2003-03-04 18:26:17 +00:00
if (tsz < foesz) {
/*XXX
2003-07-30 16:53:57 +00:00
if (fov(foe) || foe.b_sound > time || b_skill == 3) {
if ([self canSee:foe]) {
2003-07-23 22:44:15 +00:00
ent.enemy = foe;
foedist = vlen (foe.origin - ent.origin);
}
}
*/
}
}
}
}
}
}
}
}
2003-07-23 22:44:15 +00:00
}
/*
bot_weapon_switch
Pick a weapon based on range / ammo
*/
2003-07-23 22:44:15 +00:00
-(void)weapon_switch:(float)brange
{
local float it, flag = 0, pulse = 0;
local vector v;
2003-07-23 22:44:15 +00:00
it = ent.items & 127;
while (it) {
2003-07-23 22:44:15 +00:00
if ((ent.ammo_rockets >= 1) && (it & 32)) {
flag = 32;
pulse = 7;
2003-07-23 22:44:15 +00:00
} else if (ent.waterlevel <= 1 && ent.ammo_cells >= 1 && (it & 64)) {
flag = 64;
pulse = 8;
2003-07-23 22:44:15 +00:00
} else if (ent.ammo_nails >= 2 && (it & 8)) {
flag = 8;
pulse = 5;
2003-07-23 22:44:15 +00:00
} else if ((ent.ammo_rockets >= 1) && (it & 16)) {
flag = 16;
pulse = 6;
2003-07-23 22:44:15 +00:00
} else if (ent.ammo_shells >= 2 && (it & 2)) {
flag = 2;
pulse = 3;
2003-07-23 22:44:15 +00:00
} else if (ent.ammo_nails >= 1 && (it & 4)) {
flag = 4;
pulse = 4;
2003-07-23 22:44:15 +00:00
} else if (ent.ammo_shells >= 1 && (it & 1)) {
flag = 1;
pulse = 2;
2003-03-04 18:26:17 +00:00
} else {
if (pulse)
2003-07-23 22:44:15 +00:00
ent.impulse = pulse;
return;
}
2003-03-04 18:26:17 +00:00
if (brange == -1) {
if (pulse)
2003-07-23 22:44:15 +00:00
ent.impulse = pulse;
return;
}
v = weapon_range (flag);
if (brange < v_y || brange > v_z)
it = it - flag;
2003-03-04 18:26:17 +00:00
else {
if (pulse)
2003-07-23 22:44:15 +00:00
ent.impulse = pulse;
return;
}
}
2003-07-23 22:44:15 +00:00
}
2003-07-23 22:44:15 +00:00
-(void)shoot
{
// quick little function to stop making him shoot the wrong way ! Argh
local float g;
2003-07-23 22:44:15 +00:00
g = angcomp (v_angle.x, b_angle.x);
if (fabs (g) > 30)
return; // argh, too far away
2003-07-23 22:44:15 +00:00
g = angcomp (v_angle.y, b_angle.y);
if (fabs (g) > 30)
return; // not again!
2003-07-23 22:44:15 +00:00
ent.button0 = TRUE;
}
/*
Bot_fight_style
This is the core of the bot's thinking when
attacking an enemy.
*/
2003-07-23 22:44:15 +00:00
-(void)fight_style
{
local float foedist, mysz, foesz;
local vector v, v1 = '0 0 0', v2 = '0 0 0', org;
2003-07-23 22:44:15 +00:00
if (ent.enemy.health <= 0) {
ent.enemy = NIL;
return;
2003-07-23 22:44:15 +00:00
} else if (!ent.enemy.takedamage) {
ent.enemy = NIL;
return;
} else if (![self canSee:ent.enemy]) {
2003-07-23 22:44:15 +00:00
ent.enemy = NIL;
return;
}
2003-07-23 22:44:15 +00:00
org = realorigin (ent.enemy);
2003-07-30 16:53:57 +00:00
makevectors (v_angle);
// decide if I should shoot
2003-07-23 22:44:15 +00:00
foedist = vlen (org - ent.origin);
v = weapon_range (ent.weapon);
2003-03-04 18:26:17 +00:00
if (foedist > v_y && foedist < v_z) {
2003-07-23 22:44:15 +00:00
traceline (ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + v_forward * v_z, FALSE, ent);
if (vlen(trace_endpos - (ent.origin + ent.view_ofs)) >= v_y) {
// try to avoid shooting teammates
if (trace_ent.classname == "player")
2003-07-23 22:44:15 +00:00
if ((trace_ent.team == ent.team && teamplay) || (coop))
return;
2003-07-23 22:44:15 +00:00
[self shoot];
}
2003-03-04 18:26:17 +00:00
} else
2003-07-23 22:44:15 +00:00
[self weapon_switch:foedist];
2003-07-30 16:53:57 +00:00
if (!(b_aiflags & (AI_PRECISION | AI_BLIND | AI_OBSTRUCTED))) {
2003-07-23 22:44:15 +00:00
foesz = [self size_player:ent.enemy];
mysz = [self size_player:self] + 5;
2003-03-04 18:26:17 +00:00
if (foesz > mysz) {
if (teamplay) {
if (random () < 0.02) {
2003-07-30 16:45:28 +00:00
[self start_topic:5];
2003-07-30 16:53:57 +00:00
b_chattime = 1;
}
}
return;
2003-03-04 18:26:17 +00:00
} else if (mysz < 140)
return;
2003-07-30 16:53:57 +00:00
else if (avoid) {
if (avoid.velocity)
v = avoid.velocity;
else
2003-07-30 16:53:57 +00:00
v = normalize (avoid.origin - ent.origin);
v1_x = v_y;
v1_y = v_y * -1;
v2_x = v_y;
v2_y = v_y * -1;
2003-07-30 16:53:57 +00:00
foedist = vlen (avoid.origin - (ent.origin + v1));
if (foedist < vlen (avoid.origin - (ent.origin + v2)))
2003-07-23 22:44:15 +00:00
[self walkmove:v2];
else
2003-07-23 22:44:15 +00:00
[self walkmove:v1];
} else if (!(ent.enemy.flags & FL_MONSTER)) {
if (foedist + 32 < v_x)
2003-07-23 22:44:15 +00:00
[self walkmove:ent.origin - org];
else if (foedist - 32 > v_x)
2003-07-23 22:44:15 +00:00
[self walkmove:org - ent.origin];
2003-07-30 16:53:57 +00:00
else if (wallhug)
2003-07-23 22:44:15 +00:00
[self walkmove:v_right];
else
2003-07-23 22:44:15 +00:00
[self walkmove:v_right * -1];
}
2003-03-04 18:26:17 +00:00
} else {
2003-07-23 22:44:15 +00:00
foesz = [self size_player:ent.enemy];
mysz = [self size_player:self] + 5;
if (foesz > mysz)
return;
else if (mysz < 140)
return;
keys &= ~KEY_MOVE;
}
2003-07-23 22:44:15 +00:00
}
@end