2003-07-31 16:57:01 +00:00
|
|
|
/***********************************************
|
|
|
|
* *
|
|
|
|
* FrikBot Waypoints *
|
|
|
|
* "The better than roaming AI" *
|
|
|
|
* *
|
|
|
|
***********************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
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"
|
|
|
|
#include "Array.h"
|
2003-08-20 23:25:16 +00:00
|
|
|
#include "hash.h"
|
2003-07-31 16:57:01 +00:00
|
|
|
#include "List.h"
|
|
|
|
|
2003-08-20 23:25:16 +00:00
|
|
|
@static hashtab_t target_tab;
|
|
|
|
|
|
|
|
struct target_s = {
|
|
|
|
@defs (Target)
|
|
|
|
};
|
|
|
|
|
|
|
|
@static unsigned (void []ele, void []unused) target_get_hash =
|
|
|
|
{
|
|
|
|
local Target t = ele;
|
|
|
|
return ((unsigned[])&t.ent)[0];
|
|
|
|
};
|
|
|
|
|
|
|
|
@static integer (void []e1, void[]e2, void []unused) target_compare =
|
|
|
|
{
|
|
|
|
local Target t1 = e1;
|
|
|
|
local Target t2 = e2;
|
|
|
|
return t1.ent == t2.ent;
|
|
|
|
};
|
|
|
|
|
2003-07-31 16:57:01 +00:00
|
|
|
@implementation Target
|
|
|
|
|
2003-08-22 16:19:42 +00:00
|
|
|
+(Target)forEntity:(entity)e
|
2003-08-20 23:25:16 +00:00
|
|
|
{
|
|
|
|
local Target t;
|
|
|
|
local struct target_s ele;
|
|
|
|
|
2003-08-22 16:19:42 +00:00
|
|
|
if (!e)
|
2003-08-22 06:35:19 +00:00
|
|
|
return NIL;
|
|
|
|
|
2003-08-22 16:19:42 +00:00
|
|
|
if (e.classname == "player")
|
|
|
|
return e.@this;
|
2003-08-22 00:37:36 +00:00
|
|
|
|
2003-08-20 23:25:16 +00:00
|
|
|
if (!target_tab) {
|
|
|
|
target_tab = Hash_NewTable (1021, NIL, NIL, NIL);
|
|
|
|
Hash_SetHashCompare (target_tab, target_get_hash, target_compare);
|
|
|
|
}
|
2003-08-22 16:19:42 +00:00
|
|
|
ele.ent = e;
|
2003-08-20 23:25:16 +00:00
|
|
|
t = Hash_FindElement (target_tab, &ele);
|
|
|
|
if (t)
|
|
|
|
return t;
|
|
|
|
|
|
|
|
t = [[Target alloc] init];
|
2003-08-22 16:19:42 +00:00
|
|
|
t.ent = e;
|
2003-08-20 23:25:16 +00:00
|
|
|
Hash_AddElement (target_tab, t);
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
2003-07-31 16:57:01 +00:00
|
|
|
-(vector)realorigin
|
|
|
|
{
|
|
|
|
return realorigin (ent);
|
|
|
|
}
|
|
|
|
|
2003-08-18 06:30:05 +00:00
|
|
|
-(vector)origin
|
|
|
|
{
|
|
|
|
return ent.origin;
|
|
|
|
}
|
|
|
|
|
2003-07-31 16:57:01 +00:00
|
|
|
-(integer)canSee:(Target)targ ignoring:(entity)ignore
|
|
|
|
{
|
|
|
|
local vector spot1, spot2;
|
|
|
|
|
|
|
|
spot1 = ent.origin;
|
|
|
|
spot2 = [targ realorigin];
|
|
|
|
|
|
|
|
do {
|
|
|
|
traceline (spot1, spot2, TRUE, ignore);
|
|
|
|
spot1 = realorigin(trace_ent);
|
|
|
|
ignore = trace_ent;
|
|
|
|
} while ((trace_ent != world) && (trace_fraction != 1));
|
|
|
|
if (trace_endpos == spot2)
|
|
|
|
return TRUE;
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
}
|
2003-08-01 05:25:07 +00:00
|
|
|
|
|
|
|
-(void)setOrigin:(vector)org
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2003-08-18 16:48:53 +00:00
|
|
|
- (integer) recognizePlat: (integer) flag
|
2003-08-18 06:30:05 +00:00
|
|
|
{
|
|
|
|
local vector org = [self origin];
|
|
|
|
traceline (org, org - '0 0 64', TRUE, ent);
|
|
|
|
if (trace_ent != NIL)
|
|
|
|
return TRUE;
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2003-08-22 00:37:36 +00:00
|
|
|
-(integer)ishuman
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-08-22 06:35:19 +00:00
|
|
|
-(integer)priority:(Bot)bot
|
|
|
|
{
|
|
|
|
if ((ent.flags & FL_ITEM) && ent.model && ent.search_time < time) {
|
|
|
|
// ugly hack
|
2003-08-25 01:13:25 +00:00
|
|
|
if (_last != bot)
|
|
|
|
return 20;
|
2003-08-22 06:35:19 +00:00
|
|
|
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) {
|
2003-08-22 06:56:31 +00:00
|
|
|
if (sisible (ent, NIL, t.origin)) {
|
2003-08-22 06:35:19 +00:00
|
|
|
dst = tdst;
|
|
|
|
best = t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return best;
|
|
|
|
}
|
|
|
|
|
2003-08-25 01:13:25 +00:00
|
|
|
-(float)searchTime
|
|
|
|
{
|
|
|
|
return ent.search_time;
|
|
|
|
}
|
|
|
|
|
|
|
|
-(void)setSearchTime:(float)st
|
|
|
|
{
|
|
|
|
ent.search_time = st;
|
|
|
|
}
|
|
|
|
|
|
|
|
-(string)classname
|
|
|
|
{
|
|
|
|
return ent.classname;
|
|
|
|
}
|
|
|
|
|
2003-07-31 16:57:01 +00:00
|
|
|
@end
|