Exemple #1
0
void mytank_chain_refire (edict_t *self)
{
	float	r, range;

	// is enemy still valid?
	if (G_ValidTarget(self, self->enemy, true))
	{
		r = random();
		range = entdist(self, self->enemy);

		// medium range = 50% chance to continue attack
		if (range <= 512)
		{
			if (r <= 0.5)
				self->monsterinfo.currentmove = &mytank_move_attack_chain;
			else
				self->monsterinfo.currentmove = &mytank_move_attack_chain_end;

		}
		// long range = 80% chance to continue attack
		else if (r <= 0.8)
			self->monsterinfo.currentmove = &mytank_move_attack_chain;
		// end attack sequence
		else
			self->monsterinfo.currentmove = &mytank_move_attack_chain_end;
	}
	else
	{
		self->monsterinfo.currentmove = &mytank_move_attack_chain_end;
	}
	
	// don't call the attack function again for awhile!
	self->monsterinfo.attack_finished = level.time + 2.0 + random();
}
Exemple #2
0
void magmine_think(edict_t *self) {
    // check for valid position
    if (gi.pointcontents(self->s.origin) & CONTENTS_SOLID) {
        gi.dprintf("WARNING: A mag mine was removed from map due to invalid position.\n");
        safe_cprintf(self->creator, PRINT_HIGH, "Your mag mine was removed.\n");
        self->creator->magmine = NULL;
        G_FreeEdict(self);
        return;
    }

    if (!self->enemy) {
        if (magmine_findtarget(self)) {
            magmine_attack(self);
            magmine_throwsparks(self);
        }
    } else if (G_ValidTarget(self, self->enemy, true)
               && (entdist(self, self->enemy) <= self->dmg_radius)) {
        magmine_attack(self);
        magmine_throwsparks(self);
    } else {
        self->enemy = NULL;
    }

    //magmine_seteffects(self);
    M_SetEffects(self);//4.5
    self->nextthink = level.time + FRAMETIME;
}
Exemple #3
0
void mytank_reattack_blaster (edict_t *self)
{
	float r, range;

	if (G_ValidTarget(self, self->enemy, true))
	{
		r = random();
		range = entdist(self, self->enemy);

		// medium range = 80% chance to continue attack
		if (range <= 512)
		{
			if (r <= 0.8)
				self->monsterinfo.currentmove = &mytank_move_reattack_blast;
			else
				self->monsterinfo.currentmove = &mytank_move_attack_post_blast;
		}
		// long range = 50% chance to continue attack
		else
		{
			if (r <= 0.5)
				self->monsterinfo.currentmove = &mytank_move_reattack_blast;
			else
				self->monsterinfo.currentmove = &mytank_move_attack_post_blast;
		}
	}
	else
	{
		self->monsterinfo.currentmove = &mytank_move_attack_post_blast;
	}

	// don't call the attack function again for awhile!
	self->monsterinfo.attack_finished = level.time + 2.0 + random();
}
Exemple #4
0
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);
	}
}
Exemple #5
0
void mytank_refire_rocket (edict_t *self)
{
	float	r, range;
	
	if (G_ValidTarget(self, self->enemy, true))
	{
		r = random();
		range = entdist(self, self->enemy);

		// medium range
		if (range <= 512)
		{
			if (r <= 0.8)
				self->monsterinfo.currentmove = &mytank_move_attack_fire_rocket;
			else
				self->monsterinfo.currentmove = &mytank_move_attack_post_rocket;
		}
		// long range
		else
		{
			if (r <= 0.5)
				self->monsterinfo.currentmove = &mytank_move_attack_fire_rocket;
			else
				self->monsterinfo.currentmove = &mytank_move_attack_post_rocket;
		}
	}
	// end attack sequence
	else
	{
		self->monsterinfo.currentmove = &mytank_move_attack_post_rocket;
	}

	// don't call the attack function again for awhile!
	self->monsterinfo.attack_finished = level.time + 2.5 + random();
}
Exemple #6
0
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;
	}
}
Exemple #7
0
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;
	}
}
Exemple #8
0
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;

}
Exemple #9
0
void gunner_attack_grenade (edict_t *self)
{
	// continue attack sequence unless enemy is no longer valid
	if (G_ValidTarget(self, self->enemy, true))
		self->monsterinfo.currentmove = &mygunner_move_attack_grenade;
	else
		mygunnerrun(self);
}
Exemple #10
0
void mytank_attack_chain (edict_t *self)
{
	// continue attack sequence unless enemy is no longer valid
	if (G_ValidTarget(self, self->enemy, true))
		self->monsterinfo.currentmove = &mytank_move_attack_chain;
	else
		mytank_run(self);
}
Exemple #11
0
void MindAbsorb(edict_t *ent) 
{  
	edict_t *target = NULL;  
	int radius;  
	int take;  
	int total;
	int abilityLevel = ent->myskills.abilities[MIND_ABSORB].current_level;   
	
	if(ent->myskills.abilities[MIND_ABSORB].disable)   
		return;   
	if (!V_CanUseAbilities(ent, MIND_ABSORB, 0, false))   
		return;   //Cloaking and chat protected players can't steal anything
	if ((ent->flags & FL_CHATPROTECT) || (ent->svflags & SVF_NOCLIENT))   
		return;   
	
	take = MIND_ABSORB_AMOUNT_BASE + (MIND_ABSORB_AMOUNT_BONUS * abilityLevel);  
	radius = MIND_ABSORB_RADIUS_BASE + (MIND_ABSORB_RADIUS_BONUS * abilityLevel);   
	
	// scan for targets  
	while ((target = findclosestradius(target, ent->s.origin, radius)) != NULL)  
	{   
		if (target == ent)    
			continue;   
		if (!G_ValidTarget(ent, target, true))    
			continue;   
		
		total = 0;
		
		if (target->client)
		{
			if (target->client->pers.inventory[power_cube_index] < take)
				total += target->client->pers.inventory[power_cube_index];
			else
				total += take;

			target->client->pers.inventory[power_cube_index] -= total;

			// a bit of amnesia too
			target->client->ability_delay = level.time + 0.1 * abilityLevel;  
		}
		else
		{
			if (target->health < take)
				total += target->health;
			else
				total += take;
		}

		//Cap cube count to max cubes 
		if (ent->client->pers.inventory[power_cube_index] + total < MAX_POWERCUBES(ent))
			ent->client->pers.inventory[power_cube_index] += total;
		else if (ent->client->pers.inventory[power_cube_index] < MAX_POWERCUBES(ent))
			ent->client->pers.inventory[power_cube_index] = MAX_POWERCUBES(ent); 

		// those powercubes hurt!  
		T_Damage(target, ent, ent, vec3_origin, vec3_origin, vec3_origin, total, 0, DAMAGE_NO_ARMOR, MOD_MINDABSORB);
	}  
}
Exemple #12
0
void m_soldier_attack1_refire1 (edict_t *self)
{
	// continue firing if the enemy is still close, or we are standing ground
	if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.9)
		&& ((entdist(self, self->enemy) <= 512) || (self->monsterinfo.aiflags & AI_STAND_GROUND)))
	{
		self->s.frame = FRAME_attak102;
		self->monsterinfo.attack_finished = level.time + 2;
	}
}
Exemple #13
0
void Cmd_BombPlayer(edict_t *ent, float skill_mult, float cost_mult)
{
	int		cost=COST_FOR_BOMB*cost_mult;
	vec3_t	forward, right, start, end, offset;
	trace_t	tr;
//	edict_t *other=NULL;

	if (debuginfo->value)
		gi.dprintf("DEBUG: %s just called Cmd_BombPlayer()\n", ent->client->pers.netname);

	//gi.dprintf("%s\n", gi.args());

	if(ent->myskills.abilities[BOMB_SPELL].disable)
		return;

	if (!G_CanUseAbilities(ent, ent->myskills.abilities[BOMB_SPELL].current_level, cost))
		return;

	ent->client->ability_delay = level.time + DELAY_BOMB/* * cost_mult*/;

	// 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);

	ent->lastsound = level.framenum;

	// bomb an area
	//if (!Q_strcasecmp(gi.args(), "forward")) 
	if (strstr(gi.args(), "forward"))
	{
		CarpetBomb(ent, skill_mult, cost_mult);
		return;
	}
	// bomb ahead of us
	//if (!Q_strcasecmp(gi.args(), "area")) 
	if (strstr(gi.args(), "area"))
	{
		BombArea(ent, skill_mult, cost_mult);
		return;
	}

	ent->client->pers.inventory[power_cube_index] -= cost;

	AngleVectors (ent->client->v_angle, forward, right, NULL);
	VectorScale (forward, -3, ent->client->kick_origin);
	VectorSet(offset, 0, 7,  ent->viewheight-8);
	P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
	VectorMA(start, BOMBPERSON_RANGE, forward, end);
	tr = gi.trace(start, NULL, NULL, end, ent, MASK_SHOT);

	if (G_ValidTarget(ent, tr.ent, false))
		BombPerson(tr.ent, ent, skill_mult);
}
Exemple #14
0
void mygunner_continue (edict_t *self)
{
	if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.9) 
		&& (entdist(self, self->enemy) <= 512))
		self->monsterinfo.currentmove = &mygunner_move_runandshoot;
	else
		self->monsterinfo.currentmove = &mygunnermove_run;

	// don't call the attack function again for awhile!
	self->monsterinfo.attack_finished = level.time + 1.0;
}
Exemple #15
0
void gunner_refire_grenade (edict_t *self)
{
	// continue firing unless enemy is no longer valid or out of range
	if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.8)
		&& (entdist(self, self->enemy) <= 384))
		self->monsterinfo.currentmove = &mygunner_move_attack_grenade;
	else
		self->monsterinfo.currentmove = &mygunner_move_attack_grenade_end;

	// don't call the attack function again for awhile!
	self->monsterinfo.attack_finished = level.time + 0.5;
}
Exemple #16
0
void gladiator_refire (edict_t *self)
{
	// if our enemy is still valid, then continue firing
	if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.8))
	{
		self->s.frame = 49;
		GladiatorGun(self);
		return;
	}

	self->monsterinfo.attack_finished = level.time + 1.0;
}
Exemple #17
0
void minisentry_pain (edict_t *self, edict_t *other, float kick, int damage)
{
	if (!self->enemy && G_ValidTarget(self, other, true) 
		&& (entdist(self, other)<SENTRY_ATTACK_RANGE))
		self->enemy = other;

	if (level.time < self->pain_debounce_time)
		return;

	self->pain_debounce_time = level.time + 2;
	gi.sound (self, CHAN_VOICE, gi.soundindex ("tank/tnkpain2.wav"), 1, ATTN_NORM, 0);	
}
Exemple #18
0
void m_soldier_runandshoot_continue (edict_t *self)
{
	if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.9) 
		&& (entdist(self, self->enemy) <= 512))
	{
		self->monsterinfo.currentmove = &m_soldier_move_runandshoot;
		self->monsterinfo.attack_finished = level.time + 2;
		return;
	}

	self->monsterinfo.currentmove = &m_soldier_move_run;
}
Exemple #19
0
void mymedic_refire (edict_t *self)
{
	if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.5) 
		&& (entdist(self, self->enemy) <= 512))
	{
		self->s.frame = FRAME_attack19;
		return;
	}

	self->monsterinfo.currentmove = &mymedic_move_run;
	self->monsterinfo.attack_finished = level.time + random() + 1;

}
Exemple #20
0
qboolean magmine_findtarget(edict_t *self) {
    edict_t *other = NULL;

    while ((other = findclosestradius(other,
                                      self->s.origin, self->dmg_radius)) != NULL) {
        if (!G_ValidTarget(self, other, true))
            continue;
        //if (!BrainValidTarget(self, other))
        //	continue;
        self->enemy = other;
        return true;
    }
    return false;
}
Exemple #21
0
// search for nearby enemies, return true if one is found
// this is to make the medic stop healing if there is a higher priority target
// this function is the same as drone_findtarget(), except that it skips the medic check
qboolean mymedic_findenemy (edict_t *self)
{
	edict_t *target=NULL;

	while ((target = findclosestradius (target, self->s.origin, 1024)) != NULL)
	{
		if (!G_ValidTarget(self, target, true))
			continue;
		self->enemy = target;
		drone_wakeallies(self);
		return true;
	}
	return false;
}
Exemple #22
0
void mygunner_refire_chain(edict_t *self)
{
	// keep firing
	if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.8)
		&& entdist(self, self->enemy) > 128)
		self->monsterinfo.currentmove = &mygunner_move_fire_chain;
	else
		self->monsterinfo.currentmove = &mygunner_move_endfire_chain;

	//mygunner_delay(self);

	// don't call the attack function again for awhile!
	self->monsterinfo.attack_finished = level.time + 0.5;
}
Exemple #23
0
void mychick_rerocket(edict_t *self)
{
	if (G_ValidTarget(self, self->enemy, true)) 
	{
		if (random() <= 0.8 && (entdist(self, self->enemy) <= 512 || (self->monsterinfo.aiflags & AI_STAND_GROUND)))
			self->monsterinfo.currentmove = &mychick_move_attack1;
		else
			self->monsterinfo.currentmove = &mychick_move_end_attack1;
	}
	else
		self->monsterinfo.currentmove = &mychick_move_end_attack1;

	// don't call the attack function again for awhile!
	self->monsterinfo.attack_finished = level.time + 0.5;
}
Exemple #24
0
void mytank_restrike (edict_t *self)
{
	if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.6 || !self->enemy->client)
		&& (entdist(self, self->enemy) < 128))
	{
		self->monsterinfo.currentmove = &mytank_move_strike;
	}
	else
	{
		self->monsterinfo.currentmove = &mytank_move_post_strike;
	}

	// don't call the attack function again for awhile!
	self->monsterinfo.attack_finished = level.time + 0.5 + random();
}
Exemple #25
0
void gladiator_cleaver_refire (edict_t *self)
{
	if (self->monsterinfo.bonus_flags & BF_UNIQUE_LIGHTNING)
		return;

	if (G_ValidTarget(self, self->enemy, true) 
		&& (entdist(self, self->enemy) <= 96) && (random() <= 0.8))
	{
		self->s.frame = 41;
		gladiator_cleaver_swing(self);
		return;
	}

	self->monsterinfo.melee_finished = level.time + GetRandom(5, 10)*FRAMETIME;
}
Exemple #26
0
void burn_person (edict_t *target, edict_t *owner, int damage)
{
	edict_t	*flame;
	que_t *slot=NULL;

	if (level.time < pregame_time->value)
		return;
	if (que_typeexists(target->curses, CURSE_FROZEN))
		return; // attacker is frozen!
	if (!G_ValidTarget(owner, target, false))
		return;
	while ((slot = que_findtype(target->curses, slot, CURSE_BURN)) != NULL)
	{
		if (slot->time-level.time >= 9)
			return; // only allow 1 burn per second
	}

	flame = G_Spawn();
	flame->movetype = MOVETYPE_NOCLIP;
	flame->solid = SOLID_NOT;
	VectorClear(flame->mins);
	VectorClear(flame->maxs);
	flame->owner = owner;
	flame->enemy = target;
	flame->mtype = CURSE_BURN;
	flame->delay = level.time + 10;
	flame->nextthink = level.time + FRAMETIME;
	flame->PlasmaDelay = level.time + FRAMETIME;
	flame->think = fire_think;
	flame->classname = "fire";
	flame->s.sound = gi.soundindex ("weapons/bfg__l1a.wav");
	flame->dmg = damage;
	VectorCopy(target->s.origin, flame->s.origin);
	gi.linkentity (flame);

	if (!que_addent(target->curses, flame, 10))
	{
		G_FreeEdict(flame);
		return;
	}

	gi.sound (target, CHAN_ITEM, gi.soundindex ("misc/needlite.wav"), 1, ATTN_NORM, 0);
}
Exemple #27
0
void WaterTotem_think(edict_t *self, edict_t *caster)
{
	edict_t *target = NULL;

	//Find players in radius and attack them.
	while ((target = findclosestradius(target, self->s.origin, TOTEM_MAX_RANGE)) != NULL)
	{
		// (apple)
		// Since ice talent and watertotem work concurrently now, 
		// checking for chill_duration will throttle ice talent's refire.
		if (G_ValidTarget(self, target, true))
		{
			vec3_t normal;
			int talentLevel;
			float duration = WATERTOTEM_DURATION_BASE + self->monsterinfo.level * WATERTOTEM_DURATION_MULT;

			//Get a directional vector from the totem to the target.
			VectorSubtract(self->s.origin, target->s.origin, normal);

			//Talent: Ice. Damages players.
			talentLevel = getTalentLevel(caster, TALENT_ICE);
			if(talentLevel > 0)
			{
				int damage = GetRandom(10, 20) * talentLevel;
				vec3_t normal;
				
				//Damage the target
				VectorSubtract(target->s.origin, self->s.origin, normal);				
				T_Damage(target, self, self, vec3_origin, self->s.origin, 
					normal, damage, 0, DAMAGE_NO_KNOCKBACK, MOD_WATERTOTEM);
			}
			
			//Chill the target.
			target->chill_level = self->monsterinfo.level;
			target->chill_time = level.time + duration;
			//gi.dprintf("chilled %s for %.1f seconds at level %d\n", target->classname, duration, self->monsterinfo.level);
			
		}
	}
	//Next think.
	self->delay = level.time + WATERTOTEM_REFIRE_BASE + WATERTOTEM_REFIRE_MULT * self->monsterinfo.level;
}
Exemple #28
0
void mybrain_continue (edict_t *self)
{
	float	dist, chance;
	vec3_t	start, forward;

	if (!G_ValidTarget(self, self->enemy, true))
		return;

	// higher chance to continue attack if our enemy is close
	dist = entdist(self, self->enemy);
	chance = 1-dist/1024.0;

	AngleVectors(self->s.angles, forward, NULL, NULL);
	VectorMA(self->s.origin, self->maxs[1]+8, forward , start);

	if (G_IsClearPath(self->enemy, MASK_SHOT, start, self->enemy->s.origin) 
		&& (random() <= chance) && (dist <= 512))
		self->monsterinfo.nextframe = FRAME_attak206;
	mybrain_suxor(self);
}
Exemple #29
0
qboolean minisentry_findtarget (edict_t *self)
{
	edict_t	*target=NULL;

	// don't retarget too quickly
	if (self->last_move_time > level.time)
		return false;
	while ((target = findclosestradius (target, self->s.origin, SENTRY_TARGET_RANGE)) != NULL)
	{
		if (!G_ValidTarget(self, target, true))
			continue;
		if (!infov(self, target, SENTRY_FOV))
			continue;
		self->enemy = target;
		self->last_move_time = level.time + 1.0;
		gi.sound(self, CHAN_AUTO, gi.soundindex("weapons/turrspot.wav"), 1, ATTN_NORM, 0);
		return true;
	}
	return false;
}
Exemple #30
0
qboolean boss_findtarget (edict_t *boss)
{
	edict_t *target = NULL;

	while ((target = findclosestradius(target, boss->s.origin, BOSS_TARGET_RADIUS)) != NULL)
	{
		if (!G_ValidTarget(boss, target, true))
			continue;
		if (!infront(boss, target))
			continue;
		boss->enemy = target;
		//if (target->client)
		//	gi.dprintf("found %s\n", target->client->pers.netname);
		//else
		//	gi.dprintf("found target %s\n", target->classname);
	//	gi.sound (boss, CHAN_WEAPON, gi.soundindex ("tank/sight1.wav"), 1, ATTN_NORM, 0);
		return true;
	}
	return false;
}