/* Copyright (C) 1997-2001 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -------------------------------------------------------------- The ACE Bot is a product of Steve Yeager, and is available from the ACE Bot homepage, at http://www.axionfx.com/ace. This program is a modification of the ACE Bot, and is therefore in NO WAY supported by Steve Yeager. */ #include "../g_local.h" #include "ai_local.h" //ACE //========================================== // AI_EnemyAdded // Add the Player to our list //========================================== void AI_EnemyAdded( edict_t *ent ) { if( num_AIEnemies < MAX_EDICTS ) AIEnemies[num_AIEnemies++] = ent; } //========================================== // AI_EnemyRemoved // Remove the Player from list //========================================== void AI_EnemyRemoved(edict_t *ent) { int i; int pos = -1; // watch for 0 players if( num_AIEnemies < 1 ) return; // special case for only one player if( num_AIEnemies == 1 ) { num_AIEnemies = 0; return; } // Find the player for( i = 0; i < num_AIEnemies; i++ ) { if( ent == AIEnemies[i] ) pos = i; } if( pos == -1 ) return; // decrement for( i = pos; i < num_AIEnemies-1; i++ ) AIEnemies[i] = AIEnemies[i+1]; num_AIEnemies--; } qboolean Add_Armor( edict_t *ent, edict_t *other, qboolean pick_it ); //========================================== // AI_CanUseArmor // Check if we can use the armor //========================================== qboolean AI_CanUseArmor( gitem_t *item, edict_t *other ) { edict_t it_ent; if( !item ) return qfalse; if( item->tag < ARMOR_GA || item->tag >= ARMOR_TOTAL ) return qfalse; it_ent.item = item; return Add_Armor( &it_ent, other, qfalse ); } //========================================== // AI_CanPick_Ammo // Check if we can use the Ammo //========================================== qboolean AI_CanPick_Ammo (edict_t *ent, gitem_t *item) { int count; qboolean weapon; if (!ent->r.client) return qfalse; weapon = (item->type & IT_WEAPON); if ( (weapon) && ( dmflags->integer & DF_INFINITE_AMMO ) ) count = 1000; //jalfixme: we are ignoring the ent->count here, and we shouldn't //else if (ent->count) // count = ent->count; else count = item->quantity; return Add_Ammo (ent, item, count, qfalse); } //========================================== // AI_ItemIsReachable // Can we get there? Jalfixme: this needs better checks a lot //========================================== qboolean AI_ItemIsReachable(edict_t *self, vec3_t goal) { trace_t trace; vec3_t v; VectorCopy(self->r.mins,v); v[2] += AI_STEPSIZE; trap_Trace (&trace, self->s.origin, v, self->r.maxs, goal, self, MASK_NODESOLID); //trace = gi.trace ( self->s.origin, v, self->maxs, goal, self, MASK_NODESOLID ); // Yes we can see it if (trace.fraction == 1.0) return qtrue; else return qfalse; } //========================================== // AI_ItemWeight // Find out item weight //========================================== float AI_ItemWeight( edict_t *self, edict_t *it ) { float weight; if( !self->r.client ) return 0; if (!it->item) return 0; //IT_WEAPON if( it->item->type & IT_WEAPON ) { return self->ai.status.inventoryWeights[it->item->tag]; } //IT_AMMO if( it->item->type & IT_AMMO ) { return self->ai.status.inventoryWeights[it->item->tag]; } //IT_ARMOR if( it->item->type & IT_ARMOR ) { return self->ai.status.inventoryWeights[it->item->tag]; } //IT_FLAG if( it->item->type & IT_FLAG ) { return self->ai.status.inventoryWeights[it->item->tag]; } //IT_HEALTH if( it->item->type & IT_HEALTH ) { //CanPickup_Health if (!(it->style & 1)) { //#define HEALTH_IGNORE_MAX 1 if (HEALTH_TO_INT(self->health) >= self->max_health) return 0; } if (self->health >= 250 && it->count > 25) return 0; //find the weight weight = 0; if (self->health <= 250 && it->item->tag == HEALTH_MEGA)//mega weight = 1.0; else if (self->health < 100) weight = ((100 - self->health) + it->count)*0.01; weight += (self->health < 25);//we just NEED IT!!! if (weight < 0.2f) weight = 0.2f; return weight; } //IT_POWERUP if( it->item->type & IT_POWERUP ) return 0.7f; //newgametypes[start] //IT_TECH //if (it->item->flags & IT_TECH) //{ // return self->ai.status.inventoryWeights[it->item->tag]; //}//newgametypes[end] //item didn't have a recognizable item flag if (AIDevel.debugMode) G_PrintMsg( NULL, "(AI_ItemWeight) WARNING: Item with unhandled item flag:%s\n", it->classname ); return 0; } //========================================== //QUAKED item_botroam //========================================== void SP_item_botroam( edict_t *ent ) { float weight; //try to convert Q3 weights (doh) if( st.weight ) { weight = st.weight; // item_botroam weights should go between 0 and 100. // to convert odd weights to this format: if ( weight >= 1000 ) weight = 100; else if( weight >= 100 ) //include 100, cause some q3 mappers use 100, 200, 300... etc weight *= 0.1f; } else weight = 30.0f; //default value ent->count = (int)weight; }