// Electrocute whoever's in the water void ToasterElec ( ) { gedict_t *te; self->s.v.effects = 4; sound(self, 1, "weapons/lhit.wav", 1, 1); if ( self->s.v.waterlevel > 0 ) { te = findradius( world, self->s.v.origin, 950 ); while ( te ) { if ( streq( te->s.v.classname, "player" ) && te->s.v.waterlevel > 1 ) { if ( te->radsuit_finished < g_globalvars.time ) { mtf_deathmsg( 7 ); TF_T_Damage( te, self, PROG_TO_EDICT( self->s.v.owner ), 250, 2, 0 ); } } te = findradius( te, self->s.v.origin, 950 ); } dremove( self ); } else { dremove( self ); return; } }
/////////////////////////////////////////////////////////////////////// // Pick best goal based on importance and range. This function // overrides the long range goal selection for items that // are very close to the bot and are reachable. /////////////////////////////////////////////////////////////////////// void ACEAI_PickShortRangeGoal(edict_t *self) { edict_t *target; float weight,best_weight=0.0; edict_t *best; int index; // look for a target (should make more efficent later) target = findradius(NULL, self->s.origin, 200); while (target) { if (target->classname == NULL) return; // Missle avoidance code // Set our movetarget to be the rocket or grenade fired at us. if (strcmp(target->classname,"rocket")==0 || strcmp(target->classname,"grenade")==0 || strcmp(target->classname,"homing rocket")==0) { if(debug_mode) debug_printf("ROCKET ALERT!\n"); self->movetarget = target; return; } if (ACEIT_IsReachable(self,target->s.origin)) { if (infront(self, target)) { index = ACEIT_ClassnameToIndex(target->classname); weight = ACEIT_ItemNeed(self, index); if(weight > best_weight) { best_weight = weight; best = target; } } } // next target target = findradius(target, self->s.origin, 200); } if (best_weight) { self->movetarget = best; if(debug_mode && self->goalentity != self->movetarget) debug_printf("%s selected a %s for SR goal.\n",self->client->pers.netname, self->movetarget->classname); self->goalentity = best; } }
static qboolean BOT_DMclass_FindRocket( edict_t *self, vec3_t away_from_rocket ) { #define AI_ROCKET_DETECT_RADIUS 1000 #define AI_ROCKET_DANGER_RADIUS 200 edict_t *target = findradius( NULL, NULL, self->s.origin, AI_ROCKET_DETECT_RADIUS ); float min_roxx_time = 1.0f; qboolean any_rocket = qfalse; while( target ) { // Missile detection code if( target->r.svflags & SVF_PROJECTILE && target->s.type != ET_PLASMA ) // (plasmas come in bunchs so are too complex for the bot to dodge) { if( target->r.owner && target->r.owner != self ) { vec3_t end; trace_t trace; VectorMA( target->s.origin, 2, target->velocity, end ); G_Trace( &trace, target->s.origin, target->r.mins, target->r.maxs, end, target, MASK_SOLID ); if( trace.fraction < min_roxx_time ) { vec_t l; any_rocket = qtrue; min_roxx_time = trace.fraction; VectorSubtract( trace.endpos, self->s.origin, end ); // ok... end is where the impact will be. // trace.fraction is the time. if( ( l = VectorLengthFast( end ) ) < AI_ROCKET_DANGER_RADIUS ) { RotatePointAroundVector( away_from_rocket, axis_identity[UP], end, -self->s.angles[YAW] ); VectorNormalize( away_from_rocket ); if( fabs( away_from_rocket[0] ) < 0.3 ) away_from_rocket[0] = 0; if( fabs( away_from_rocket[1] ) < 0.3 ) away_from_rocket[1] = 0; away_from_rocket[2] = 0; away_from_rocket[0] *= -1.0f; away_from_rocket[1] *= -1.0f; if( nav.debugMode && bot_showcombat->integer > 2 ) G_PrintChasersf( self, "%s: ^1projectile dodge: ^2%f, %f d=%f^7\n", self->ai.pers.netname, away_from_rocket[0], away_from_rocket[1], l ); } } } } target = findradius( target, NULL, self->s.origin, AI_ROCKET_DETECT_RADIUS ); } return any_rocket; #undef AI_ROCKET_DETECT_RADIUS #undef AI_ROCKET_DANGER_RADIUS }
void p_berserk_crush (edict_t *self, int damage, float range, int mod) { trace_t tr; edict_t *other=NULL; vec3_t v; // must be on the ground to punch if (!self->groundentity) return; self->lastsound = level.framenum; gi.sound (self, CHAN_AUTO, gi.soundindex ("tank/tnkatck5.wav"), 1, ATTN_NORM, 0); while ((other = findradius(other, self->s.origin, range)) != NULL) { if (!G_ValidTarget(self, other, true)) continue; if (!nearfov(self, other, 0, 30)) continue; VectorSubtract(other->s.origin, self->s.origin, v); VectorNormalize(v); tr = gi.trace(self->s.origin, NULL, NULL, other->s.origin, self, (MASK_PLAYERSOLID | MASK_MONSTERSOLID)); T_Damage (other, self, self, v, other->s.origin, tr.plane.normal, damage, damage, 0, mod); other->velocity[2] += damage / 2; } }
/* ======================== objective_area ======================== */ void objective_area_think (edict_t *self) { edict_t *ent = NULL; int count = 0; int newteam = 0; int delay; self->nextthink = level.time + FRAMETIME; if (self->delay) // if there's a counter running { } while ((ent = findradius(ent, self->s.origin, self->obj_area)) != NULL) { if (!ent->inuse) continue; if (!IsValidPlayer(ent)) continue; newteam = ent->client->resp.team_on->index; if (newteam != self->obj_owner) count++; //gi.dprintf(DEVELOPER_MSG_GAME, "Found %d players\n", count); } if (count >= self->obj_count) { team_list[self->obj_owner]->score -= self->obj_loss; self->obj_owner = team_list[newteam]->index; team_list[self->obj_owner]->score += self->obj_gain; if (team_list[self->obj_owner]->time_to_win) // If there already is a counter somwhere else { if (team_list[self->obj_owner]->time_to_win > (self->obj_time + level.time) ) // If the counter is longer, shorten it up to this one team_list[self->obj_owner]->time_to_win = (self->obj_time + level.time); } else // there is no counter team_list[self->obj_owner]->time_to_win = (self->obj_time + level.time); delay = (int)(team_list[self->obj_owner]->time_to_win - level.time); if ((delay/60) >= 1) safe_bprintf(PRINT_HIGH, "Team %s has %i minutes before they win the battle.\n", team_list[self->obj_owner]->teamname, (delay/60)); else safe_bprintf(PRINT_HIGH, "Team %s has %i seconds before they win the battle.\n", team_list[self->obj_owner]->teamname, delay); gi.sound(self, CHAN_NO_PHS_ADD, gi.soundindex(va("%s/objectives/area_cap.wav", team_list[self->obj_owner]->teamid)), 1, 0, 0); if (dedicated->value) safe_cprintf(NULL, PRINT_HIGH, "Objective %s taken by team %s!\n", self->obj_name, team_list[self->obj_owner]->teamname); centerprintall("Objective %s taken\n by team %s!\n", self->obj_name, team_list[self->obj_owner]->teamname); } }
/* ============= zSchoolAllVisiable Creates a list of all entities in the raduis of Z_RADUISLISTSIZE ============== */ void zCreateRaduisList(edict_t *self) { edict_t *head, *list; vec3_t vec; if(self->zRaduisList) { // already created for this think, don't bother doing it again... return; } head = NULL; list = self; while(1) { head = findradius(head, self->s.origin, Z_RADUISLISTSIZE); if(head == NULL) break; if(head != self) { list->zRaduisList = head; VectorSubtract(self->s.origin, head->s.origin, vec); head->zDistance = VectorLength(vec); list = head; } } list->zRaduisList = NULL; };
/* ============ T_RadiusDamage ============ */ void T_RadiusDamage (edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, int mod) { float points; edict_t *ent = NULL; vec3_t v; vec3_t dir; while ((ent = findradius(ent, inflictor->s.origin, radius)) != NULL) { if (ent == ignore) continue; if (!ent->takedamage) continue; VectorAdd (ent->mins, ent->maxs, v); VectorMA (ent->s.origin, 0.5, v, v); VectorSubtract (inflictor->s.origin, v, v); points = damage - 0.5 * VectorLength (v); if (ent == attacker) points = points * 0.5; if (points > 0) { if (CanDamage (ent, inflictor)) { VectorSubtract (ent->s.origin, inflictor->s.origin, dir); T_Damage (ent, inflictor, attacker, dir, inflictor->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, mod); } } } }
edict_t *medic_FindDeadMonster (edict_t *self) { edict_t *ent = NULL; edict_t *best = NULL; while ((ent = findradius(ent, self->s.origin, 1024)) != NULL) { if (ent == self) continue; if (!(ent->svflags & SVF_MONSTER)) continue; if (ent->monsterinfo.aiflags & AI_GOOD_GUY) continue; if (ent->owner) continue; if (ent->health > 0) continue; if (ent->nextthink) continue; if (!visible(self, ent)) continue; if (!best) { best = ent; continue; } if (ent->max_health <= best->max_health) continue; best = ent; } return best; }
void PlagueCloudSpawn (edict_t *ent) { float radius; edict_t *e=NULL; if (ent->myskills.abilities[PLAGUE].disable) return; if (!V_CanUseAbilities(ent, PLAGUE, 0, false)) return; if ((ent->myskills.class_num == CLASS_POLTERGEIST) && !ent->mtype && !PM_PlayerHasMonster(ent)) return; // can't use this in human form radius = PLAGUE_DEFAULT_RADIUS+PLAGUE_ADDON_RADIUS*ent->myskills.abilities[PLAGUE].current_level; if (radius > PLAGUE_MAX_RADIUS) radius = PLAGUE_MAX_RADIUS; // find someone nearby to infect while ((e = findradius(e, ent->s.origin, radius)) != NULL) { if (!G_ValidTarget(ent, e, true)) continue; // if (HasActiveCurse(e, CURSE_PLAGUE)) if (que_typeexists(e->curses, CURSE_PLAGUE)) continue; // holy water grants temporary immunity to curses if (e->holywaterProtection > level.time) continue; PlagueCloud(ent, e); } }
void mytank_meleeattack (edict_t *self) { int damage; trace_t tr; edict_t *other=NULL; vec3_t v; // tank must be on the ground to punch if (!self->groundentity) return; self->lastsound = level.framenum; damage = 100+20*self->monsterinfo.level; gi.sound (self, CHAN_AUTO, gi.soundindex ("tank/tnkatck5.wav"), 1, ATTN_NORM, 0); while ((other = findradius(other, self->s.origin, 128)) != NULL) { if (!G_ValidTarget(self, other, true)) continue; // bosses don't have to be facing their enemy, others do //if ((self->monsterinfo.control_cost < 3) && !nearfov(self, other, 0, 60))//!infront(self, other)) // continue; VectorSubtract(other->s.origin, self->s.origin, v); VectorNormalize(v); tr = gi.trace(self->s.origin, NULL, NULL, other->s.origin, self, (MASK_PLAYERSOLID | MASK_MONSTERSOLID)); T_Damage (other, self, self, v, tr.endpos, tr.plane.normal, damage, 200, 0, MOD_TANK_PUNCH); //other->velocity[2] += 200;//damage / 2; } }
void plague_think (edict_t *self) { int dmg; float radius; edict_t *e=NULL; // plague self-terminates if: if (!G_EntIsAlive(self->owner) || !G_EntIsAlive(self->enemy) //someone dies || (self->owner->flags & FL_WORMHOLE) // owner enters a wormhole || (self->owner->client->tball_delay > level.time) //owner tballs away || (self->owner->flags & FL_CHATPROTECT) //3.0 owner is in chatprotect || ((self->owner->myskills.class_num == CLASS_POLTERGEIST) && (!self->owner->mtype) && !PM_PlayerHasMonster(self->owner)) //3.0 poltergeist is in human form || que_findtype(self->enemy->curses, NULL, HEALING) != NULL) //3.0 player is blessed with healing { que_removeent(self->enemy->curses, self, true); return; } VectorCopy(self->enemy->s.origin, self->s.origin); // follow enemy radius = PLAGUE_DEFAULT_RADIUS+PLAGUE_ADDON_RADIUS*self->owner->myskills.abilities[PLAGUE].current_level; if (radius > PLAGUE_MAX_RADIUS) radius = PLAGUE_MAX_RADIUS; // find someone nearby to infect while ((e = findradius(e, self->s.origin, radius)) != NULL) { if (e == self->enemy) continue; if (!G_ValidTarget(self, e, true)) continue; // don't allow more than one curse of the same type if (que_typeexists(e->curses, CURSE_PLAGUE)) continue; // holy water grants temporary immunity to curses if (e->holywaterProtection > level.time) continue; // spawn another plague cloud on this entity PlagueCloud(self->owner, e); } if (level.time > self->wait) { dmg = (float)self->owner->myskills.abilities[PLAGUE].current_level/10 * ((float)self->enemy->max_health/20); if (!self->enemy->client && strcmp(self->enemy->classname, "player_tank") != 0) dmg *= 2; // non-clients take double damage (helps with pvm) if (dmg < 1) dmg = 1; if (dmg > 100) dmg = 100; T_Damage(self->enemy, self->enemy, self->owner, vec3_origin, self->enemy->s.origin, vec3_origin, dmg, 0, DAMAGE_NO_ABILITIES, MOD_PLAGUE); // hurt 'em self->wait = level.time + PLAGUE_DELAY; } self->nextthink = level.time + FRAMETIME; }
void bfg_explode ( edict_t *self ) { edict_t *ent; float points; vec3_t v; float dist; if ( !self ) { return; } if ( self->s.frame == 0 ) { /* the BFG effect */ ent = NULL; while ( ( ent = findradius ( ent, self->s.origin, self->dmg_radius ) ) != NULL ) { if ( !ent->takedamage ) { continue; } if ( ent == self->owner ) { continue; } if ( !CanDamage ( ent, self ) ) { continue; } if ( !CanDamage ( ent, self->owner ) ) { continue; } VectorAdd ( ent->mins, ent->maxs, v ); VectorMA ( ent->s.origin, 0.5, v, v ); VectorSubtract ( self->s.origin, v, v ); dist = VectorLength ( v ); points = self->radius_dmg * ( 1.0 - sqrt ( dist / self->dmg_radius ) ); if ( ent == self->owner ) { points = points * 0.5; } gi.WriteByte ( svc_temp_entity ); gi.WriteByte ( TE_BFG_EXPLOSION ); gi.WritePosition ( ent->s.origin ); gi.multicast ( ent->s.origin, MULTICAST_PHS ); T_Damage ( ent, self, self->owner, self->velocity, ent->s.origin, vec3_origin, ( q_int32_t ) points, 0, DAMAGE_ENERGY, MOD_BFG_EFFECT ); } } self->nextthink = level.time + FRAMETIME; self->s.frame++; if ( self->s.frame == 5 ) { self->think = G_FreeEdict; } }
edict_t *medic_FindDeadMonster (edict_t *self) { edict_t *ent = NULL; edict_t *best = NULL; while ((ent = findradius(ent, self->s.origin, 1024)) != NULL) { if (ent == self) continue; if (!(ent->svflags & SVF_MONSTER)) continue; if (ent->monsterinfo.aiflags & AI_GOOD_GUY) continue; if (ent->owner) continue; if (ent->health > 0) continue; if (ent->nextthink && (ent->think != M_FliesOff) && (ent->think != M_FliesOn)) continue; // check to make sure we haven't bailed on this guy already if ((ent->monsterinfo.badMedic1 == self) || (ent->monsterinfo.badMedic2 == self)) continue; if (!visible(self, ent)) continue; if (embedded(ent)) continue; if (!canReach(self,ent)) continue; if (!best) { best = ent; continue; } if (ent->max_health <= best->max_health) continue; best = ent; } if(best) { self->oldenemy = self->enemy; self->enemy = best; self->enemy->owner = best; self->monsterinfo.aiflags |= AI_MEDIC; self->monsterinfo.aiflags &= ~AI_MEDIC_PATROL; self->monsterinfo.medicTries = 0; self->movetarget = self->goalentity = NULL; self->enemy->monsterinfo.healer = self; self->timestamp = level.time + MEDIC_TRY_TIME; FoundTarget (self); if(developer->value) gi.dprintf("medic found dead monster: %s at %s\n", best->classname,vtos(best->s.origin)); } return best; }
void GetNearbyTeammates(edict_t *self, char *buf) { unsigned char nearby_teammates[10][16]; int nearby_teammates_num, l; edict_t *ent = NULL; nearby_teammates_num = 0; while ((ent = findradius(ent, self->s.origin, 1500)) != NULL) { if (ent == self || !ent->client || !CanDamage(ent, self) || OnSameTeam(ent, self)) continue; strncpy(nearby_teammates[nearby_teammates_num], ent->client->pers.netname, 15); nearby_teammates[nearby_teammates_num][15] = 0; // in case their name is 15 chars... nearby_teammates_num++; if (nearby_teammates_num >= 10) break; } if (nearby_teammates_num == 0) { strcpy(buf, "nobody"); return; } for (l = 0; l < nearby_teammates_num; l++) { if (l == 0) { strcpy(buf, nearby_teammates[l]); } else { if (nearby_teammates_num == 2) { strcat(buf, " and "); strcat(buf, nearby_teammates[l]); } else { if (l == (nearby_teammates_num - 1)) { strcat(buf, ", and "); strcat(buf, nearby_teammates[l]); } else { strcat(buf, ", "); strcat(buf, nearby_teammates[l]); } } } } }
edict_t *medic_FindDeadMonster (edict_t *self) { float radius; edict_t *ent = NULL; edict_t *best = NULL; if (self->monsterinfo.aiflags & AI_STAND_GROUND) radius = MEDIC_MAX_HEAL_DISTANCE; else radius = 1024; while ((ent = findradius(ent, self->s.origin, radius)) != NULL) { if (ent == self) continue; if (!(ent->svflags & SVF_MONSTER)) continue; if (ent->monsterinfo.aiflags & AI_GOOD_GUY) continue; // check to make sure we haven't bailed on this guy already if ((ent->monsterinfo.badMedic1 == self) || (ent->monsterinfo.badMedic2 == self)) continue; if (ent->monsterinfo.healer) // FIXME - this is correcting a bug that is somewhere else // if the healer is a monster, and it's in medic mode .. continue .. otherwise // we will override the healer, if it passes all the other tests if ((ent->monsterinfo.healer->inuse) && (ent->monsterinfo.healer->health > 0) && (ent->monsterinfo.healer->svflags & SVF_MONSTER) && (ent->monsterinfo.healer->monsterinfo.aiflags & AI_MEDIC)) continue; if (ent->health > 0) continue; if ((ent->nextthink) && !((ent->think == M_FliesOn) || (ent->think == M_FliesOff))) continue; if (!visible(self, ent)) // if (!canReach(self, ent)) continue; if (!strncmp(ent->classname, "player", 6)) // stop it from trying to heal player_noise entities continue; // FIXME - there's got to be a better way .. // make sure we don't spawn people right on top of us if (realrange(self, ent) <= MEDIC_MIN_DISTANCE) continue; if (!best) { best = ent; continue; } if (ent->max_health <= best->max_health) continue; best = ent; } if (best) self->timestamp = level.time + MEDIC_TRY_TIME; return best; }
// Knightmare- check for grenades and lasers qboolean gekk_check_jump_hazard (edict_t *self, qboolean watertoland, qboolean farjump) { vec3_t v; float distance; trace_t trace; vec3_t oldorg, neworg, forward, dir; vec_t g1, g2; edict_t *grenade; if (!self->enemy) // pararnoia return false; //gi.dprintf ("Gekk: checking jump for hazards...\n"); VectorSubtract(self->s.origin, self->enemy->s.origin, v); distance = VectorLength(v); VectorCopy (self->s.origin, oldorg); VectorCopy (self->enemy->s.origin, neworg); AngleVectors (self->s.angles, forward, NULL, NULL); trace = gi.trace (self->s.origin, self->mins, self->maxs, neworg, self, MASK_MONSTERSOLID); // Lazarus: Don't intentionally move closer to a grenade, // but don't perform this check if we're already evading some // other problem (maybe even this grenade) if(!(self->monsterinfo.aiflags & AI_CHASE_THING)) { grenade = NULL; while( (grenade = findradius(grenade,neworg,128)) != NULL) { if(!grenade->inuse) continue; if(!grenade->classname) continue; if(!Q_strcasecmp(grenade->classname,"grenade") || !Q_strcasecmp(grenade->classname,"hgrenade")) { VectorSubtract(grenade->s.origin, oldorg, dir); g1 = VectorLength(dir); VectorSubtract(grenade->s.origin, neworg, dir); g2 = VectorLength(dir); if (g2 < g1) { //gi.dprintf ("Gekk: Jump would put me closer to live grenade, aborting\n"); return false; } } } } // Maybe we could could check for lasers using badarea fields? return true; }
void Cmd_Nova_f (edict_t *ent, int frostLevel, float skill_mult, float cost_mult) { int damage, cost=NOVA_COST*cost_mult; if (!G_CanUseAbilities(ent, ent->myskills.abilities[NOVA].current_level, cost)) return; if (ent->myskills.abilities[NOVA].disable) return; damage = (NOVA_DEFAULT_DAMAGE+NOVA_ADDON_DAMAGE*ent->myskills.abilities[NOVA].current_level)*skill_mult; T_RadiusDamage(ent, ent, damage, ent, NOVA_RADIUS, MOD_NOVA); //Talent: Frost Nova if(frostLevel > 0) { edict_t *target = NULL; while ((target = findradius(target, ent->s.origin, FROSTNOVA_RADIUS)) != NULL) { if (target == ent) continue; if (!target->takedamage) continue; if (!visible1(ent, target)) continue; //curse with holyfreeze target->chill_level = 2 * frostLevel; target->chill_time = level.time + 3.0; //3 second duration if (random() > 0.5) gi.sound(target, CHAN_ITEM, gi.soundindex("spells/blue1.wav"), 1, ATTN_NORM, 0); else gi.sound(target, CHAN_ITEM, gi.soundindex("spells/blue3.wav"), 1, ATTN_NORM, 0); } } // write a nice effect so everyone knows we've cast a spell gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_TELEPORT_EFFECT); gi.WritePosition (ent->s.origin); gi.multicast (ent->s.origin, MULTICAST_PVS); NovaExplosionEffect(ent->s.origin); gi.sound (ent, CHAN_WEAPON, gi.soundindex("spells/novaelec.wav"), 1, ATTN_NORM, 0); ent->client->ability_delay = level.time + NOVA_DELAY/* * cost_mult*/; ent->client->pers.inventory[power_cube_index] -= cost; // calling entity made a sound, used to alert monsters ent->lastsound = level.framenum; }
int CheckArea( gedict_t * obj, gedict_t * builder ) { vec3_t src; vec3_t end; int pos; gedict_t *te; pos = CheckAreaNew( obj, builder ); if ( pos == 0 ) return 0; pos = trap_pointcontents( PASSVEC3( obj->s.v.origin ) ); if ( pos == CONTENT_SOLID || pos == CONTENT_SKY ) return 0; src[0] = obj->s.v.origin[0] + 24; src[1] = obj->s.v.origin[1] + 24; src[2] = obj->s.v.origin[2] + 16; pos = trap_pointcontents( PASSVEC3( src ) ); if ( pos == CONTENT_SOLID || pos == CONTENT_SKY ) return 0; end[0] = obj->s.v.origin[0] - 16; end[1] = obj->s.v.origin[1] - 16; end[2] = obj->s.v.origin[2] - 16; traceline( PASSVEC3( src ), PASSVEC3( end ), 1, obj ); if ( g_globalvars.trace_fraction != 1 ) return 0; pos = trap_pointcontents( PASSVEC3( end ) ); if ( pos == CONTENT_SOLID || pos == CONTENT_SKY ) return 0; src[0] = obj->s.v.origin[0] - 16; src[1] = obj->s.v.origin[1] + 16; src[2] = obj->s.v.origin[2] + 16; pos = trap_pointcontents( PASSVEC3( src ) ); if ( pos == CONTENT_SOLID || pos == CONTENT_SKY ) return 0; end[0] = obj->s.v.origin[0] + 16; end[1] = obj->s.v.origin[1] - 16; end[2] = obj->s.v.origin[2] - 16; traceline( PASSVEC3( src ), PASSVEC3( end ), 1, obj ); if ( g_globalvars.trace_fraction != 1 ) return 0; pos = trap_pointcontents( PASSVEC3( end ) ); if ( pos == CONTENT_SOLID || pos == CONTENT_SKY ) return 0; traceline( PASSVEC3( builder->s.v.origin ), PASSVEC3( obj->s.v.origin ), 1, builder ); if ( g_globalvars.trace_fraction != 1 ) return 0; te = findradius( world, obj->s.v.origin, 64 ); if ( te ) return 0; return 1; }
qboolean NearbyLasers (edict_t *ent, vec3_t org) { edict_t *e=NULL; while((e = findradius(e, org, 8)) != NULL) { // is this a laser than we own? if (e && e->inuse && G_EntExists(e->activator) && (e->activator == ent) && !strcmp(e->classname, "emitter")) return true; } return false; }
/* ==================== M_MoveAwayFromFlare ==================== */ qboolean M_MoveAwayFromFlare(edict_t *self, float dist) { edict_t *e = NULL; edict_t *goal = NULL; vec3_t delta; vec3_t forward; // find the closest flare while(1) { e = findradius(e, self->s.origin, 256); if (e == NULL) break; if (Q_stricmp(e->classname, "flare") == 0) break; } goal = G_Spawn(); self->goalentity = goal; if (e == NULL) { // just move forward AngleVectors(self->s.angles, forward, NULL, NULL); VectorMA(self->s.origin, 128, forward, goal->s.origin); } else { VectorSubtract(self->s.origin, e->s.origin, delta); VectorNormalize(delta); VectorMA(self->s.origin, 128, delta, goal->s.origin); } if (rand() & (7 == 1)) { // set the ideal_yaw VectorSubtract(goal->s.origin, self->s.origin, delta); self->ideal_yaw = vectoyaw(delta); } if ( (rand()&3)==1 || !SV_StepDirection (self, self->ideal_yaw, dist)) { SV_NewChaseDir (self, goal, dist); } self->goalentity = NULL; G_FreeEdict(goal); return true; }
// returns true if there is a nearby, visible player boss qboolean findNearbyBoss (edict_t *self) { edict_t *other=NULL; while ((other = findradius(other, self->s.origin, BOSS_ALLY_BONUS_RANGE)) != NULL) { if (!IsABoss(other)) continue; if (!G_EntIsAlive(other)) continue; return true; } return false; }
qboolean NearbyProxy (edict_t *ent, vec3_t org) { edict_t *e=NULL; while((e = findradius(e, org, 8)) != NULL) { // is this a proxy than we own? if (e && e->inuse && G_EntExists(e->owner) && (e->owner == ent) && !strcmp(e->classname, "proxygrenade")) return true; } return false; }
void salvation_think (edict_t *self) { int radius; edict_t *other=NULL; que_t *slot=NULL; // check status of owner if (!CheckAuraOwner(self, COST_FOR_SALVATION)) { que_removeent(self->owner->auras, self, true); return; } // use cubes if (!(level.framenum % DEFAULT_AURA_FRAMES)) { int cube_cost = DEFAULT_AURA_COST; self->owner->client->pers.inventory[power_cube_index] -= cube_cost; } que_addent(self->owner->auras, self, DEFAULT_AURA_DURATION); // move aura with owner VectorCopy(self->owner->s.origin,self->s.origin); self->nextthink = level.time + FRAMETIME; if (level.framenum % DEFAULT_AURA_SCAN_FRAMES) return; radius = 256; // scan for targets while ((other = findradius (other, self->s.origin, radius)) != NULL) { slot = NULL; if (other == self->owner) continue; if (!G_EntExists(other)) continue; if (other->health < 1) continue; if (OnSameTeam(self->owner, other) < 2) continue; if (!visible(self->owner, other)) continue; slot = que_findtype(other->auras, slot, AURA_SALVATION); if (slot && (slot->ent->owner != self->owner)) continue; que_addent(other->auras, self, DEFAULT_AURA_DURATION); } }
static edict_t * FindEnemy(edict_t * self, int radius) { // loop through all nearby entities, looking for targets edict_t * ent = 0; int nPriority = 0; // 1 grenades, 2 clients, 3 pets int nPotentialPriority = 0; edict_t * enemy = 0; while ((ent = findradius(ent, self->s.origin, 500)) != NULL) { if ((ent->flags & FL_NOTARGET)||(ent->svflags & SVF_NOCLIENT)) continue; if (!ent->inuse || !ent->takedamage || (ent->health <= 0)) continue; if (EntIsMonster(ent)) { if (OnSameTeam(ent, self)) continue; nPotentialPriority = 3; } else if (EntIsClient(ent)) { if (OnSameTeam(ent, self)) continue; nPotentialPriority = 2; } else { // first priority is grenades // modify this if you don't want pets shooting grenades nPotentialPriority = 1; } if (nPriority>nPotentialPriority) continue; if (!visible(self, ent)) continue; // remember this candidate enemy enemy = ent; nPriority = nPotentialPriority; } // return best we found (might be zero) return enemy; }
/* ============ T_RadiusDamage ============ */ void T_RadiusDamage (edict_t * inflictor, edict_t * attacker, float damage, edict_t * ignore, float radius, int mod) { float points; edict_t *ent = NULL; vec3_t v; vec3_t dir; while ((ent = findradius (ent, inflictor->s.origin, radius)) != NULL) { if (ent == ignore) continue; if (!ent->takedamage) continue; VectorAdd (ent->mins, ent->maxs, v); VectorMA (ent->s.origin, 0.5, v, v); VectorSubtract (inflictor->s.origin, v, v); points = damage - 0.5 * VectorLength (v); //zucc reduce damage for crouching, max is 32 when standing if (ent->maxs[2] < 20) { points = points * 0.5; // hefty reduction in damage } //if (ent == attacker) //points = points * 0.5; if (points > 0) { #ifdef _DEBUG if (0 == Q_stricmp (ent->classname, "func_explosive")) { CGF_SFX_ShootBreakableGlass (ent, inflictor, 0, mod); } else #endif if (CanDamage (ent, inflictor)) { VectorSubtract (ent->s.origin, inflictor->s.origin, dir); // zucc scaled up knockback(kick) of grenades T_Damage (ent, inflictor, attacker, dir, ent->s.origin, vec3_origin, (int) (points * .75), (int) (points * .75), DAMAGE_RADIUS, mod); } } } }
void CurseRadiusAttack (edict_t *caster, int type, int range, int radius, float duration, qboolean isCurse) { edict_t *e=NULL, *f=NULL; // write a nice effect so everyone knows we've cast a spell gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_TELEPORT_EFFECT); gi.WritePosition (caster->s.origin); gi.multicast (caster->s.origin, MULTICAST_PVS); caster->client->idle_frames = 0; caster->client->ability_delay = level.time;// for monster hearing (check if ability was recently used/cast) // find a target closest to the caster's reticle while ((e = findclosestreticle(e, caster, range)) != NULL) { if (!CanCurseTarget(caster, e, type, isCurse, true)) continue; if (entdist(caster, e) > range) continue; if (!infront(caster, e)) continue; if (!curse_add(e, caster, type, 0, duration)) continue; CurseMessage(caster, e, type, duration, isCurse); // target anything in-range of this entity while ((f = findradius(f, e->s.origin, radius)) != NULL) { if (!CanCurseTarget(caster, f, type, isCurse, false)) continue; if (f == e) continue; if (!visible(e, f)) continue; if (!curse_add(f, caster, type, 0, duration)) continue; CurseMessage(caster, f, type, duration, isCurse); } break; } }
/* ** wicked ** * jump grenade -- think ================= Jumpgen_Think ================= */ void Jumpgen_Think (edict_t *ent) { edict_t *blip = NULL; vec3_t dir, up; while ((blip = findradius(blip, ent->s.origin, 50)) != NULL){ if (!strcmp(blip->classname, "player")){ VectorCopy( dir, blip->velocity ); AngleVectors (dir, NULL, NULL, up); blip->takedamage = DAMAGE_NO; VectorMA(blip->velocity, 1000, up, blip->velocity); blip->takedamage = DAMAGE_YES; G_FreeEdict (ent); } } ent->think = Jumpgen_Think; ent->nextthink = level.time + .1; }
void homing_rocket_think(edict_t *ent) { vec3_t to_target; vec_t speed; if (ent->homing_target == NULL) { while ((ent->homing_target = findradius(ent->homing_target, ent->s.origin, 1000)) != NULL) { if (!ent->homing_target->client) continue; if (!ent->homing_target->takedamage) continue; if (ent->homing_target->health <= 0) continue; if (!visible(ent, ent->homing_target)) continue; if (ent->homing_target == ent->owner) continue; break; } ent->nextthink = level.time + .1; return; } else { VectorSubtract(ent->homing_target->s.origin, ent->s.origin, to_target); to_target[2] += 16; VectorNormalize(to_target); VectorScale(to_target, 0.3, to_target); VectorAdd(to_target, ent->movedir, to_target); VectorNormalize(to_target); VectorCopy(to_target, ent->movedir); vectoangles(to_target, ent->s.angles); speed = VectorLength(ent->velocity); VectorScale(to_target, speed, ent->velocity); ent->nextthink = level.time + .1; } }
void boss_punch (edict_t *self) { int damage; trace_t tr; edict_t *other=NULL; vec3_t v; if (!self->groundentity) return; damage = TANK_PUNCH_INITIAL_DAMAGE+TANK_PUNCH_ADDON_DAMAGE*self->monsterinfo.level; // T_RadiusDamage(self, self, damage, self, TANK_PUNCH_RADIUS, 0); gi.sound (self, CHAN_AUTO, gi.soundindex ("tank/tnkatck5.wav"), 1, ATTN_NORM, 0); while ((other = findradius(other, self->s.origin, 256)) != NULL) { if (other == self) continue; if (!other->inuse) continue; if (!other->takedamage) continue; if (other->solid == SOLID_NOT) continue; if (!other->groundentity) continue; if (OnSameTeam(self, other)) continue; if (!visible(self, other)) continue; VectorSubtract(other->s.origin, self->s.origin, v); VectorNormalize(v); tr = gi.trace(self->s.origin, NULL, NULL, other->s.origin, self, (MASK_PLAYERSOLID | MASK_MONSTERSOLID)); T_Damage (other, self, self, v, other->s.origin, tr.plane.normal, damage, damage, 0, MOD_TANK_PUNCH); other->velocity[2] += damage / 2; } }
int CheckAreaNew( gedict_t * obj, gedict_t * builder ) { gedict_t *te; vec3_t end; TraceCapsule( PASSVEC3( obj->s.v.origin ), PASSVEC3( obj->s.v.origin ), 0, obj, PASSVEC3( obj->s.v.mins), PASSVEC3( obj->s.v.maxs) ); if ( g_globalvars.trace_startsolid == 1 ) { VectorCopy( obj->s.v.origin, end ); end[2] -= 48; TraceCapsule( PASSVEC3( obj->s.v.origin ), PASSVEC3( end ), 0, obj, PASSVEC3( obj->s.v.mins), obj->s.v.maxs[0], obj->s.v.maxs[1], 4); VectorCopy( g_globalvars.trace_endpos, end ); end[2]++; TraceCapsule( PASSVEC3( end ), PASSVEC3( end ), 0, obj, PASSVEC3( obj->s.v.mins), PASSVEC3( obj->s.v.maxs) ); if ( g_globalvars.trace_startsolid == 1 ) return 0; } te = findradius( world, obj->s.v.origin, 64 ); if ( te ) return 0; return 1; }