Example #1
0
void path_corner_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
{
	vec3_t		v;
	edict_t		*next;

	if (other->movetarget != self)
		return;
	
	if (other->enemy)
		return;

#ifdef IML_Q2_EXTENSIONS
	if (!ai_movetarget_is_active(other))
		return;
#endif

	if (self->pathtarget)
	{
		char *savetarget;

		savetarget = self->target;
		self->target = self->pathtarget;
		G_UseTargets (self, other);
		self->target = savetarget;
	}

	if (self->target)
		next = G_PickTarget(self->target);
	else
		next = NULL;

	if ((next) && (next->spawnflags & PATH_CORNER_TELEPORT))
	{
		VectorCopy (next->s.origin, v);
		v[2] += next->mins[2];
		v[2] -= other->mins[2];
		VectorCopy (v, other->s.origin);
		next = G_PickTarget(next->target);
		other->s.event = EV_OTHER_TELEPORT;
	}

	// 18 Aug 2004 - IML - madhura - path_corner enhancements
	// was: other->goalentity = other->movetarget = next;
	other->movetarget = next;
	other->goalentity = NULL;
	if (ai_movetarget_is_active(other))
		other->goalentity = other->movetarget;

	if (self->wait)
	{
		other->monsterinfo.pausetime = level.time + self->wait;
		other->monsterinfo.stand (other);
		return;
	}

	// 18 Aug 2004 - IML - madhura - path_corner enhancements
	// was: if (!other->movetarget)
	if (!other->goalentity)
	{
		other->monsterinfo.pausetime = level.time + 100000000;
		other->monsterinfo.stand (other);
	}
	else
	{
		VectorSubtract (other->goalentity->s.origin, other->s.origin, v);
		other->ideal_yaw = vectoyaw (v);
	}
}
Example #2
0
void HintTestNext (edict_t *self, edict_t *hint)
{
	edict_t		*next=NULL;
	edict_t		*e;
	vec3_t		dir;

	self->monsterinfo.aiflags &= ~AI_HINT_TEST;
	if(self->goalentity == hint)
		self->goalentity = NULL;
	if(self->movetarget == hint)
		self->movetarget = NULL;
	if(self->monsterinfo.pathdir == 1)
	{
		if(hint->hint_chain)
			next = hint->hint_chain;
		else
			self->monsterinfo.pathdir = -1;
	}
	if(self->monsterinfo.pathdir == -1)
	{
		e = hint_chain_starts[hint->hint_chain_id];
		while(e)
		{
			if(e->hint_chain == hint)
			{
				next = e;
				break;
			}
			e = e->hint_chain;
		}
	}
	if(!next)
	{
		self->monsterinfo.pathdir = 1;
		next = hint->hint_chain;
	}
	if(next)
	{
		self->hint_chain_id = next->hint_chain_id;
		VectorSubtract(next->s.origin, self->s.origin, dir);
		self->ideal_yaw = vectoyaw(dir);
		self->goalentity = self->movetarget = next;
		self->monsterinfo.pausetime = 0;
		self->monsterinfo.aiflags = AI_HINT_TEST;
		// run for it
		self->monsterinfo.run (self);
		gi.dprintf("%s (%s): Reached hint_path %s,\nsearching for hint_path %s at %s. %s\n",
			self->classname, (self->targetname ? self->targetname : "<noname>"),
			(hint->targetname ? hint->targetname : "<noname>"),
			(next->targetname ? next->targetname : "<noname>"),
			vtos(next->s.origin),
			(visible(self,next) ? "I see it." : "I don't see it."));
	}
	else
	{
		self->monsterinfo.pausetime = level.time + 100000000;
		self->monsterinfo.stand (self);
		gi.dprintf("%s (%s): Error finding next/previous hint_path from %s at %s.\n",
			self->classname, (self->targetname ? self->targetname : "<noname>"),
			(hint->targetname ? hint->targetname : "<noname>"),
			vtos(hint->s.origin));
	}
}
Example #3
0
void monster_start_go (edict_t *self)
{
	vec3_t	v;

	if (self->health <= 0)
	{
		if (self->max_health <= 0)
			InitiallyDead(self);
		return;
	}

	// Lazarus: move_origin for func_monitor
	if(!VectorLength(self->move_origin))
		VectorSet(self->move_origin,0,0,self->viewheight);

	// check for target to point_combat and change to combattarget
	if (self->target)
	{
		qboolean	notcombat;
		qboolean	fixup;
		edict_t		*target;

		target = NULL;
		notcombat = false;
		fixup = false;
		while ((target = G_Find (target, FOFS(targetname), self->target)) != NULL)
		{
			if (strcmp(target->classname, "point_combat") == 0)
			{
				self->combattarget = self->target;
				fixup = true;
			}
			else
			{
				notcombat = true;
			}
		}
		if (notcombat && self->combattarget)
			gi.dprintf("%s at %s has target with mixed types\n", self->classname, vtos(self->s.origin));
		if (fixup)
			self->target = NULL;
	}

	// validate combattarget
	if (self->combattarget)
	{
		edict_t		*target;

		target = NULL;
		while ((target = G_Find (target, FOFS(targetname), self->combattarget)) != NULL)
		{
			if (strcmp(target->classname, "point_combat") != 0)
			{
				gi.dprintf("%s at (%i %i %i) has a bad combattarget %s : %s at (%i %i %i)\n",
					self->classname, (int)self->s.origin[0], (int)self->s.origin[1], (int)self->s.origin[2],
					self->combattarget, target->classname, (int)target->s.origin[0], (int)target->s.origin[1],
					(int)target->s.origin[2]);
			}
		}
	}

	if (self->target)
	{
		self->goalentity = self->movetarget = G_PickTarget(self->target);
		if (!self->movetarget)
		{
			gi.dprintf ("%s can't find target %s at %s\n", self->classname, self->target, vtos(self->s.origin));
			self->target = NULL;
			self->monsterinfo.pausetime = 100000000;
			self->monsterinfo.stand (self);
		}
		else if (strcmp (self->movetarget->classname, "path_corner") == 0)
		{
			// Lazarus: Don't wipe out target for trigger spawned monsters
			//          that aren't triggered yet
			if( ! (self->spawnflags & SF_MONSTER_TRIGGER_SPAWN) ) {
				VectorSubtract (self->goalentity->s.origin, self->s.origin, v);
				self->ideal_yaw = self->s.angles[YAW] = vectoyaw(v);
				self->monsterinfo.walk (self);
				self->target = NULL;
			}
		}
		else
		{
			self->goalentity = self->movetarget = NULL;
			self->monsterinfo.pausetime = 100000000;
			self->monsterinfo.stand (self);
		}
	}
	else
	{
		self->monsterinfo.pausetime = 100000000;
		self->monsterinfo.stand (self);
	}

	self->think = monster_think;
	self->nextthink = level.time + FRAMETIME;
}
Example #4
0
/*
===========
FindTarget

Self is currently not attacking anything, so try to find a target

Returns TRUE if an enemy was sighted

When a player fires a missile, the point of impact becomes a fakeplayer so
that monsters that see the impact will respond as if they had seen the
player.

To avoid spending too much time, only a single client (or fakeclient) is
checked each frame.  This means multi player games will have slightly
slower noticing monsters.
============
*/
bool FindTarget (edict_t *self)
{
	edict_t		*client;
	bool	heardit;
	bool    noise;
	int			r;

	if (self->monsterinfo.aiflags & AI_GOOD_GUY)
	{
		if (self->goalentity && self->goalentity->r.inuse && self->goalentity->classname)
		{
			if (strcmp(self->goalentity->classname, "target_actor") == 0)
				return false;
		}

		//FIXME look for monsters?
		return false;
	}

	// if we're going to a combat point, just proceed
	if (self->monsterinfo.aiflags & AI_COMBAT_POINT)
		return false;

// if the first spawnflag bit is set, the monster will only wake up on
// really seeing the player, not another monster getting angry or hearing
// something

// revised behavior so they will wake up if they "see" a player make a noise
// but not weapon impact/explosion noises

	heardit = false;
	if ((level.sight_entity_framenum+1 >= level.framenum) && !(self->spawnflags & 1) )
	{
		client = level.sight_entity;
		if (client->enemy == self->enemy)
		{
			return false;
		}
	}
	else if (level.sound_entity_framenum+1 >= level.framenum)
	{
		client = level.sound_entity;
		heardit = true;
	}
	else if (!(self->enemy) && (level.sound2_entity_framenum+1 >= level.framenum) && !(self->spawnflags & 1) )
	{
		client = level.sound2_entity;
		heardit = true;
	}
	else
	{
		client = level.sight_client;
		if (!client)
			return false;	// no clients to get mad at
	}

	// if the entity went away, forget it
	if (!client->r.inuse)
		return false;
	if (client == self->enemy)
		return true;	// JDC false;

	noise = strcmp(client->classname, "player_noise") == 0;
	if (!noise && (client->r.svflags & SVF_NOCLIENT))
		return false;

	if (client->r.client)
	{
		if (client->flags & FL_NOTARGET)
			return false;
	}
	else if (client->r.svflags & SVF_MONSTER)
	{
		if (!client->enemy)
			return false;
		if (client->enemy->flags & FL_NOTARGET)
			return false;
	}
	else if (heardit)
	{
		if (client->r.owner->flags & FL_NOTARGET)
			return false;
	}
	else
		return false;

	if (!heardit)
	{
		r = range (self, client);

		if (r == RANGE_FAR)
			return false;

// this is where we would check invisibility

		// is client in an spot too dark to be seen?
//		if (client->light_level <= 5)
//			return false;

		if (!G_Visible (self, client))
		{
			return false;
		}

		if (r == RANGE_NEAR)
		{
			if (client->show_hostile < level.time && !G_InFront (self, client))
			{
				return false;
			}
		}
		else if (r == RANGE_MID)
		{
			if (!G_InFront (self, client))
			{
				return false;
			}
		}

		self->enemy = client;

		if (!noise)
		{
			self->monsterinfo.aiflags &= ~AI_SOUND_TARGET;

			if (!self->enemy->r.client)
			{
				self->enemy = self->enemy->enemy;
				if (!self->enemy->r.client)
				{
					self->enemy = NULL;
					return false;
				}
			}
		}
	}
	else	// heardit
	{
		vec3_t	temp;

		if (self->spawnflags & 1)
		{
			if (!G_Visible (self, client))
				return false;
		}

		VectorSubtract (client->s.origin, self->s.origin, temp);

		if (VectorLength(temp) > 1000)	// too far to hear
		{
			return false;
		}

		// check area portals - if they are different and not connected then we can't hear it
		if (client->r.areanum != self->r.areanum)
			if (!trap_CM_AreasConnected(self->r.areanum, client->r.areanum))
				return false;

		self->ideal_yaw = vectoyaw(temp);
		M_ChangeYaw (self);

		// hunt the sound for a bit; hopefully find the real player
		self->monsterinfo.aiflags |= AI_SOUND_TARGET;
		self->enemy = client;
	}

//
// got one
//
	FoundTarget (self);

	if (!(self->monsterinfo.aiflags & AI_SOUND_TARGET) && (self->monsterinfo.sight))
		self->monsterinfo.sight (self, self->enemy);

	return true;
}
Example #5
0
qboolean PM_AdjustAngleForWallRun( gentity_t *ent, usercmd_t *ucmd, qboolean doMove )
{
    if (( ent->client->ps.legsAnim == BOTH_WALL_RUN_RIGHT || ent->client->ps.legsAnim == BOTH_WALL_RUN_LEFT ) && ent->client->ps.legsAnimTimer > 500 )
    {   //wall-running and not at end of anim
        //stick to wall, if there is one
        vec3_t	rt, traceTo, mins = {ent->mins[0],ent->mins[1],0}, maxs = {ent->maxs[0],ent->maxs[1],24}, fwdAngles = {0, ent->client->ps.viewangles[YAW], 0};
        trace_t	trace;
        float	dist, yawAdjust;

        AngleVectors( fwdAngles, NULL, rt, NULL );
        if ( ent->client->ps.legsAnim == BOTH_WALL_RUN_RIGHT )
        {
            dist = 128;
            yawAdjust = -90;
        }
        else
        {
            dist = -128;
            yawAdjust = 90;
        }
        VectorMA( ent->currentOrigin, dist, rt, traceTo );
        gi.trace( &trace, ent->currentOrigin, mins, maxs, traceTo, ent->s.number, ent->clipmask, (EG2_Collision)0, 0);
        if ( trace.fraction < 1.0f && trace.plane.normal[2] == 0.0f )
        {   //still a vertical wall there
            //FIXME: don't pull around 90 turns
            //FIXME: simulate stepping up steps here, somehow?
            if ( ent->s.number || !player_locked )
            {
                if ( ent->client->ps.legsAnim == BOTH_WALL_RUN_RIGHT )
                {
                    ucmd->rightmove = 127;
                }
                else
                {
                    ucmd->rightmove = -127;
                }
            }
            if ( ucmd->upmove < 0 )
            {
                ucmd->upmove = 0;
            }
            if ( ent->NPC )
            {   //invalid now
                VectorClear( ent->client->ps.moveDir );
            }
            //make me face perpendicular to the wall
            ent->client->ps.viewangles[YAW] = vectoyaw( trace.plane.normal )+yawAdjust;
            if ( ent->client->ps.viewEntity <= 0 || ent->client->ps.viewEntity >= ENTITYNUM_WORLD )
            {   //don't clamp angles when looking through a viewEntity
                SetClientViewAngle( ent, ent->client->ps.viewangles );
            }
            ucmd->angles[YAW] = ANGLE2SHORT( ent->client->ps.viewangles[YAW] ) - ent->client->ps.delta_angles[YAW];
            if ( ent->s.number || !player_locked )
            {
                if ( doMove )
                {
                    //push me forward
                    vec3_t	fwd;
                    float	zVel = ent->client->ps.velocity[2];
                    if ( zVel > forceJumpStrength[FORCE_LEVEL_2]/2.0f )
                    {
                        zVel = forceJumpStrength[FORCE_LEVEL_2]/2.0f;
                    }
                    if ( ent->client->ps.legsAnimTimer > 500 )
                    {   //not at end of anim yet
                        fwdAngles[YAW] = ent->client->ps.viewangles[YAW];
                        AngleVectors( fwdAngles, fwd, NULL, NULL );
                        //FIXME: or MA?
                        float speed = 175;
                        if ( ucmd->forwardmove < 0 )
                        {   //slower
                            speed = 100;
                        }
                        else if ( ucmd->forwardmove > 0 )
                        {
                            speed = 250;//running speed
                        }
                        VectorScale( fwd, speed, ent->client->ps.velocity );
                    }
                    ent->client->ps.velocity[2] = zVel;//preserve z velocity
                    VectorMA( ent->client->ps.velocity, -128, trace.plane.normal, ent->client->ps.velocity );
                    //pull me toward the wall, too
                    //VectorMA( ent->client->ps.velocity, dist, rt, ent->client->ps.velocity );
                }
            }
            ucmd->forwardmove = 0;
            return qtrue;
        }
        else if ( doMove )
        {   //stop it
            if ( ent->client->ps.legsAnim == BOTH_WALL_RUN_RIGHT )
            {
                NPC_SetAnim( ent, SETANIM_BOTH, BOTH_WALL_RUN_RIGHT_STOP, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
            }
            else if ( ent->client->ps.legsAnim == BOTH_WALL_RUN_LEFT )
            {
                NPC_SetAnim( ent, SETANIM_BOTH, BOTH_WALL_RUN_LEFT_STOP, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
            }
        }
    }
    return qfalse;
}
Example #6
0
void target_actor_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
{
	vec3_t	v;

	if (other->movetarget != self)
		return;
	
	if (other->enemy)
		return;

	other->goalentity = other->movetarget = NULL;

	if (self->message)
	{
		int		n;
		edict_t	*ent;

		for (n = 1; n <= game.maxclients; n++)
		{
			ent = &g_edicts[n];
			if (!ent->inuse)
				continue;
			gi.cprintf (ent, PRINT_CHAT, "%s: %s\n", actor_names[(other - g_edicts)%MAX_ACTOR_NAMES], self->message);
		}
	}

	if (self->spawnflags & 1)		//jump
	{
		other->velocity[0] = self->movedir[0] * self->speed;
		other->velocity[1] = self->movedir[1] * self->speed;
		
		if (other->groundentity)
		{
			other->groundentity = NULL;
			other->velocity[2] = self->movedir[2];
			gi.sound(other, CHAN_VOICE, gi.soundindex("player/male/jump1.wav"), 1, ATTN_NORM, 0);
		}
	}

	if (self->spawnflags & 2)	//shoot
	{
	}
	else if (self->spawnflags & 4)	//attack
	{
		other->enemy = G_PickTarget(self->pathtarget);
		if (other->enemy)
		{
			other->goalentity = other->enemy;
			if (self->spawnflags & 32)
				other->monsterinfo.aiflags |= AI_BRUTAL;
			if (self->spawnflags & 16)
			{
				other->monsterinfo.aiflags |= AI_STAND_GROUND;
				actor_stand (other);
			}
			else
			{
				actor_run (other);
			}
		}
	}

	if (!(self->spawnflags & 6) && (self->pathtarget))
	{
		char *savetarget;

		savetarget = self->target;
		self->target = self->pathtarget;
		G_UseTargets (self, other);
		self->target = savetarget;
	}

	other->movetarget = G_PickTarget(self->target);

	if (!other->goalentity)
		other->goalentity = other->movetarget;

	if (!other->movetarget && !other->enemy)
	{
		other->monsterinfo.pausetime = level.time + 100000000;
		other->monsterinfo.stand (other);
	}
	else if (other->movetarget == other->goalentity)
	{
		VectorSubtract (other->movetarget->s.origin, other->s.origin, v);
		other->ideal_yaw = vectoyaw (v);
	}
}
Example #7
0
qboolean
Boss2_CheckAttack(edict_t *self)
{
	vec3_t spot1, spot2;
	vec3_t temp;
	float chance;
	trace_t tr;
	int enemy_range;
	float enemy_yaw;

	if (!self)
	{
		return false;
	}

	if (self->enemy->health > 0)
	{
		/* see if any entities are in the way of the shot */
		VectorCopy(self->s.origin, spot1);
		spot1[2] += self->viewheight;
		VectorCopy(self->enemy->s.origin, spot2);
		spot2[2] += self->enemy->viewheight;

		tr = gi.trace( spot1, NULL, NULL, spot2, self,
				CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_SLIME |
				CONTENTS_LAVA);

		/* do we have a clear shot? */
		if (tr.ent != self->enemy)
		{
			return false;
		}
	}

	enemy_range = range(self, self->enemy);
	VectorSubtract(self->enemy->s.origin, self->s.origin, temp);
	enemy_yaw = vectoyaw(temp);

	self->ideal_yaw = enemy_yaw;

	/* melee attack */
	if (enemy_range == RANGE_MELEE)
	{
		if (self->monsterinfo.melee)
		{
			self->monsterinfo.attack_state = AS_MELEE;
		}
		else
		{
			self->monsterinfo.attack_state = AS_MISSILE;
		}

		return true;
	}

	/* missile attack */
	if (!self->monsterinfo.attack)
	{
		return false;
	}

	if (level.time < self->monsterinfo.attack_finished)
	{
		return false;
	}

	if (enemy_range == RANGE_FAR)
	{
		return false;
	}

	if (self->monsterinfo.aiflags & AI_STAND_GROUND)
	{
		chance = 0.4;
	}
	else if (enemy_range == RANGE_MELEE)
	{
		chance = 0.8;
	}
	else if (enemy_range == RANGE_NEAR)
	{
		chance = 0.8;
	}
	else if (enemy_range == RANGE_MID)
	{
		chance = 0.8;
	}
	else
	{
		return false;
	}

	if (random() < chance)
	{
		self->monsterinfo.attack_state = AS_MISSILE;
		self->monsterinfo.attack_finished = level.time + 2 * random();
		return true;
	}

	if (self->flags & FL_FLY)
	{
		if (random() < 0.3)
		{
			self->monsterinfo.attack_state = AS_SLIDING;
		}
		else
		{
			self->monsterinfo.attack_state = AS_STRAIGHT;
		}
	}

	return false;
}
Example #8
0
/*
======================
M_MoveToGoal
======================
*/
void M_MoveToGoal (edict_t *ent, float dist)
{
	edict_t		*goal;

	goal = ent->goalentity;

	if (ent->holdtime > level.time) // stay in-place for medic healing
		return;

	if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM)) && !ent->waterlevel)
	{
		//gi.dprintf("not touching ground\n");
		return;
	}

// if the next step hits the enemy, return immediately
	if (ent->enemy && (ent->enemy->solid == SOLID_BBOX) 
		&& SV_CloseEnough (ent, ent->enemy, dist) )
//GHz START
	{
		vec3_t v;

		// we need to keep turning to avoid getting stuck doing nothing
		if (ent->goalentity && ent->goalentity->inuse) // 3.89 make sure the monster still has a goal!
		{
			VectorSubtract(ent->goalentity->s.origin, ent->s.origin, v);
			VectorNormalize(v);
			ent->ideal_yaw = vectoyaw(v);
			M_ChangeYaw(ent);
		}
		return;
	}
//GHz END

	// dont move so fast in the water
	if (!(ent->flags & (FL_FLY|FL_SWIM)) && (ent->waterlevel > 1))
		dist *= 0.5;

// bump around...
	// if we can't take a step, try moving in another direction
	if (!SV_StepDirection (ent, ent->ideal_yaw, dist, true))
	{
		//gi.dprintf("couldnt step\n");
		// if the monster hasn't moved much, then increment
		// the number of frames it has been stuck
		if (distance(ent->s.origin, ent->monsterinfo.stuck_org) < 64)
			ent->monsterinfo.stuck_frames++;
		else
			ent->monsterinfo.stuck_frames = 0;

		// record current position for comparison
		VectorCopy(ent->s.origin, ent->monsterinfo.stuck_org);

		// attempt a course-correction
		if (ent->inuse && (level.time > ent->monsterinfo.bump_delay))
		{
			//gi.dprintf("tried course correction %s\n", ent->goalentity?"true":"false");
			SV_NewChaseDir (ent, goal, dist);
			ent->monsterinfo.bump_delay = level.time + FRAMETIME*GetRandom(2, 5);
			return;
		}
	}
}
Example #9
0
void
Trap_Think(edict_t *ent)
{
	edict_t *target = NULL;
	edict_t *best = NULL;
	vec3_t vec;
	int len, i;
	int oldlen = 8000;
	vec3_t forward, right, up;

	if (!ent)
	{
		return;
	}

	if (ent->timestamp < level.time)
	{
		BecomeExplosion1(ent);
		return;
	}

	ent->nextthink = level.time + 0.1;

	if (!ent->groundentity)
	{
		return;
	}

	/* ok lets do the blood effect */
	if (ent->s.frame > 4)
	{
		if (ent->s.frame == 5)
		{
			if (ent->wait == 64)
			{
				gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/trapdown.wav"),
					   	1, ATTN_IDLE, 0);
			}

			ent->wait -= 2;
			ent->delay += level.time;

			for (i = 0; i < 3; i++)
			{
				best = G_Spawn();

				if (strcmp(ent->enemy->classname, "monster_gekk") == 0)
				{
					best->s.modelindex = gi.modelindex("models/objects/gekkgib/torso/tris.md2");
					best->s.effects |= TE_GREENBLOOD;
				}
				else if (ent->mass > 200)
				{
					best->s.modelindex = gi.modelindex("models/objects/gibs/chest/tris.md2");
					best->s.effects |= TE_BLOOD;
				}
				else
				{
					best->s.modelindex = gi.modelindex("models/objects/gibs/sm_meat/tris.md2");
					best->s.effects |= TE_BLOOD;
				}

				AngleVectors(ent->s.angles, forward, right, up);

				RotatePointAroundVector(vec, up, right, ((360.0 / 3) * i) + ent->delay);
				VectorMA(vec, ent->wait / 2, vec, vec);
				VectorAdd(vec, ent->s.origin, vec);
				VectorAdd(vec, forward, best->s.origin);

				best->s.origin[2] = ent->s.origin[2] + ent->wait;

				VectorCopy(ent->s.angles, best->s.angles);

				best->solid = SOLID_NOT;
				best->s.effects |= EF_GIB;
				best->takedamage = DAMAGE_YES;

				best->movetype = MOVETYPE_TOSS;
				best->svflags |= SVF_MONSTER;
				best->deadflag = DEAD_DEAD;

				VectorClear(best->mins);
				VectorClear(best->maxs);

				best->watertype = gi.pointcontents(best->s.origin);

				if (best->watertype & MASK_WATER)
				{
					best->waterlevel = 1;
				}

				best->nextthink = level.time + 0.1;
				best->think = G_FreeEdict;
				gi.linkentity(best);
			}

			if (ent->wait < 19)
			{
				ent->s.frame++;
			}

			return;
		}

		ent->s.frame++;

		if (ent->s.frame == 8)
		{
			ent->nextthink = level.time + 1.0;
			ent->think = G_FreeEdict;

			best = G_Spawn();
			SP_item_foodcube(best);
			VectorCopy(ent->s.origin, best->s.origin);
			best->s.origin[2] += 16;
			best->velocity[2] = 400;
			best->count = ent->mass;
			gi.linkentity(best);
			return;
		}

		return;
	}

	ent->s.effects &= ~EF_TRAP;

	if (ent->s.frame >= 4)
	{
		ent->s.effects |= EF_TRAP;
		VectorClear(ent->mins);
		VectorClear(ent->maxs);
	}

	if (ent->s.frame < 4)
	{
		ent->s.frame++;
	}

	while ((target = findradius(target, ent->s.origin, 256)) != NULL)
	{
		if (target == ent)
		{
			continue;
		}

		if (!(target->svflags & SVF_MONSTER) && !target->client)
		{
			continue;
		}

		if (target->health <= 0)
		{
			continue;
		}

		if (!visible(ent, target))
		{
			continue;
		}

		if (!best)
		{
			best = target;
			continue;
		}

		VectorSubtract(ent->s.origin, target->s.origin, vec);
		len = VectorLength(vec);

		if (len < oldlen)
		{
			oldlen = len;
			best = target;
		}
	}

	/* pull the enemy in */
	if (best)
	{
		vec3_t forward;

		if (best->groundentity)
		{
			best->s.origin[2] += 1;
			best->groundentity = NULL;
		}

		VectorSubtract(ent->s.origin, best->s.origin, vec);
		len = VectorLength(vec);

		if (best->client)
		{
			VectorNormalize(vec);
			VectorMA(best->velocity, 250, vec, best->velocity);
		}
		else
		{
			best->ideal_yaw = vectoyaw(vec);
			M_ChangeYaw(best);
			AngleVectors(best->s.angles, forward, NULL, NULL);
			VectorScale(forward, 256, best->velocity);
		}

		gi.sound(ent, CHAN_VOICE, gi.soundindex(
						"weapons/trapsuck.wav"), 1, ATTN_IDLE, 0);

		if (len < 32)
		{
			if (best->mass < 400)
			{
				T_Damage(best, ent, ent->owner, vec3_origin, best->s.origin,
						vec3_origin, 100000, 1, 0, MOD_TRAP);
				ent->enemy = best;
				ent->wait = 64;
				VectorCopy(ent->s.origin, ent->s.old_origin);
				ent->timestamp = level.time + 30;

				if (deathmatch->value)
				{
					ent->mass = best->mass / 4;
				}
				else
				{
					ent->mass = best->mass / 10;
				}

				/* ok spawn the food cube */
				ent->s.frame = 5;
			}
			else
			{
				BecomeExplosion1(ent);
				return;
			}
		}
	}
}
Example #10
0
void path_corner_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
{
	vec3_t		v;
	edict_t		*next;

	if (other->movetarget != self)
		return;
	
	if (other->enemy)
		return;

	if (self->pathtarget)
	{
		char *savetarget;

		savetarget = self->target;
		self->target = self->pathtarget;
		G_UseTargets (self, other);
		self->target = savetarget;
	}

	if (self->target)
		next = G_PickTarget(self->target);
	else
		next = NULL;

	if ((next) && (next->spawnflags & 1))
	{
		VectorCopy (next->s.origin, v);
		v[2] += next->mins[2];
		v[2] -= other->mins[2];
		VectorCopy (v, other->s.origin);
		next = G_PickTarget(next->target);
	}

	other->goalentity = other->movetarget = next;

	if (self->wait)
	{
		if(other->goalentity)
		{
			VectorSubtract (other->goalentity->s.origin, other->s.origin, v);
			other->ideal_yaw = vectoyaw (v);
		}

		other->monsterinfo.pausetime = level.time + self->wait;
		other->monsterinfo.stand (other);
		return;
	}

	if (!other->movetarget)
	{
		other->monsterinfo.pausetime = level.time + 100000000;
		other->monsterinfo.stand (other);
	}
	else
	{
		VectorSubtract (other->goalentity->s.origin, other->s.origin, v);
		other->ideal_yaw = vectoyaw (v);
	}
}
Example #11
0
/*
==================
AI_BeginAttack

  Returns true if OK to attack, false otherwise

  May start a new movement for the character, to straighten up, or avoid something/someone
==================
*/
qboolean AI_BeginAttack( edict_t *self )
{
	vec3_t	vec;
	float	dist;


	// Ridah, 7-5-99, If they've been ordered to attack us by a client, get mad at them also
	if (self->enemy && self->enemy->leader)
		AI_MakeEnemy( self, self->enemy->leader, 0 );


	if (!self->enemy || (self->enemy->health <= 0))
	{
		self->cast_info.currentmove = self->cast_info.move_stand;
		return false;
	}

	dist = VectorDistance( self->s.origin, self->enemy->s.origin );


	// Ridah, 19-may-99, Grenade AI
	if (self->cast_info.aiflags & AI_GRENADE_GUY)
	{
		if (( self->s.origin[2] - self->enemy->s.origin[2] ) < -256)
		{
			if (self->cast_info.currentmove != self->cast_info.move_avoid_run)
				AI_EndAttack(self);		// try find something else to do

			return false;
		}
	}


	if (	!(self->cast_info.aiflags & AI_SIDE_ATTACK))
// Ridah 7/5/99, fixes shooting with back to player (happens in SR1 courtyard sometimes)
//		&&	(	(dist > FACE_ANIM_DIST)
//			 ||	(self->cast_info.aiflags & AI_FACE_ATTACK)))
	{

		if (!directly_infront(self, self->enemy))
		{	// we need to straighten up
			float	dist;

			VectorSubtract( self->enemy->s.origin, self->s.origin, vec );
			dist = VectorNormalize( vec );
			self->ideal_yaw = vectoyaw( vec );

			if ((dist > 384) && (self->maxs[2] == self->cast_info.standing_max_z))
			{
				int side_result;

				side_result = AI_SideTrace( self, 48, 90, SIDE_RANDOM );

				if (side_result && self->cast_info.move_lside_step)
				{
					if (side_result < 0)
						self->cast_info.currentmove = self->cast_info.move_lside_step;
					else
						self->cast_info.currentmove = self->cast_info.move_rside_step;
				}
				else
				{
					self->cast_info.currentmove = self->cast_info.move_avoid_walk;
				}

				return false;
			}
			else
			{
				M_ChangeYaw(self);
			}

		}

	}
/*
	if (	(self->cast_info.move_avoid_reverse_run)
		&&	(self->cast_info.last_reverse < (level.time - 5))
		&&	(dist < 64))
	{
		// trace a line backwards, make sure we can move there
		if ( AI_YawTrace( self, 64, 180 ) )
		{
			self->cast_info.currentmove = self->cast_info.move_avoid_reverse_run;
			self->cast_info.last_reverse = level.time;
			return false;
		}
	}
*/
	if (!AI_ClearSight(self, self->enemy, true))
	{	// can't see them directly, will we hit another enemy? if so keep firing

		static vec3_t mins = { -8, -8,  -4 };
		static vec3_t maxs = {  8,  8,   4 };
		vec3_t	start, end;
		trace_t tr;
		cast_memory_t	*tr_memory;

		VectorCopy( self->s.origin, start );
		start[2] += self->viewheight - 8;

		VectorCopy( self->enemy->s.origin, end );
		end[2] += self->enemy->viewheight - 8;

		tr = gi.trace( start, mins, maxs, end, self, MASK_PLAYERSOLID );

		if (tr.fraction < 1)
		{
			if (tr.ent == world)
			{
				if (self->cast_info.currentmove != self->cast_info.move_avoid_run)
					AI_EndAttack(self);		// try find something else to do

				return false;
			}
			else if (tr.ent->svflags & SVF_MONSTER || tr.ent->client)
			{
				tr_memory = level.global_cast_memory[self->character_index][tr.ent->character_index];

				if (!tr_memory || !(tr_memory->flags & MEMORY_HOSTILE_ENEMY))
				{
					if (self->cast_info.currentmove != self->cast_info.move_avoid_run)
						AI_EndAttack(self);		// try find something else to do

					return false;
				}
			}
		}
	}

	if (self->dont_takecover_time == 99999)
	{	// attack for at least 2 seconds
		if (!(self->cast_info.aiflags & AI_MELEE))
			self->dont_takecover_time = level.time + 2 + random()*4;
		else
			self->dont_takecover_time = 0;
	}

	return true;
}
Example #12
0
/*
=============
ai_run

The monster has an enemy it is trying to kill
=============
*/
void ai_run( float dist )
{
	vec3_t tmpv;

	if ( k_bloodfest )
	{
		if ( (int)self->s.v.flags & FL_SWIM )
		{
			dist *= 5; // let fish swim faster in bloodfest mode.
		}
		else if ( self->bloodfest_boss )
		{
			dist *= 2; // let boss move faster
		}
	}

	movedist = dist;

	// see if the enemy is dead
	if ( ISDEAD( PROG_TO_EDICT( self->s.v.enemy ) ) || ( (int)PROG_TO_EDICT( self->s.v.enemy )->s.v.flags & FL_NOTARGET ) )
	{
		self->s.v.enemy = EDICT_TO_PROG( world );

		// FIXME: look all around for other targets
		if ( self->oldenemy && ISLIVE( self->oldenemy ) && !( (int)self->oldenemy->s.v.flags & FL_NOTARGET ) )
		{
			self->s.v.enemy = EDICT_TO_PROG( self->oldenemy );
			HuntTarget ();
		}
		else
		{
			if ( !self->movetarget || self->movetarget == world )
			{
				if ( self->th_stand )
					self->th_stand();
			}
			else
			{
				if ( self->th_walk )
					self->th_walk();
			}

			return;
		}
	}

	self->show_hostile = g_globalvars.time + 1;		// wake up other monsters

// check knowledge of enemy
	enemy_vis = visible( PROG_TO_EDICT( self->s.v.enemy ) );
	if ( enemy_vis )
		self->search_time = g_globalvars.time + 5; // does not search for enemy next 5 seconds

// look for other coop players
	if ( coop && self->search_time < g_globalvars.time )
	{
		if ( FindTarget() )
		{
			// this is fix for too frequent enemy sighting, required for bloodfest mode.
			if ( !visible( PROG_TO_EDICT( self->s.v.enemy ) ) )
			{
				self->search_time = g_globalvars.time + 5; // does not search for enemy next 5 seconds
			}
			return;
		}
	}

	enemy_infront = infront( PROG_TO_EDICT( self->s.v.enemy ) );
	enemy_range   = range( PROG_TO_EDICT( self->s.v.enemy ) );
	VectorSubtract( PROG_TO_EDICT( self->s.v.enemy )->s.v.origin, self->s.v.origin, tmpv);
	enemy_yaw     = vectoyaw( tmpv );

	if ( self->attack_state == AS_MISSILE )
	{
		//dprint ("ai_run_missile\n");
		ai_run_missile();
		return;
	}

	if ( self->attack_state == AS_MELEE )
	{
		//dprint ("ai_run_melee\n");
		ai_run_melee();
		return;
	}

	if ( CheckAnyAttack() )
		return;					// beginning an attack

	if ( self->attack_state == AS_SLIDING )
	{
		ai_run_slide();
		return;
	}

	// head straight in
	movetogoal( dist );		// done in C code...
}
Example #13
0
/*
=============
ai_run

The monster has an enemy it is trying to kill
=============
*/
void ai_run (edict_t *self, float dist)
{
	vec3_t		v;
	edict_t		*tempgoal;
	edict_t		*save;
	bool	newcourse;
	edict_t		*marker;
	float		d1, d2;
	trace_t		tr;
	vec3_t		v_forward, v_right;
	float		left, center, right;
	vec3_t		left_target, right_target;

	// if we're going to a combat point, just proceed
	if (self->monsterinfo.aiflags & AI_COMBAT_POINT)
	{
		M_MoveToGoal (self, dist);
		return;
	}

	if (self->monsterinfo.aiflags & AI_SOUND_TARGET)
	{
		VectorSubtract (self->s.origin, self->enemy->s.origin, v);
		if (VectorLength(v) < 64)
		{
			self->monsterinfo.aiflags |= (AI_STAND_GROUND | AI_TEMP_STAND_GROUND);
			self->monsterinfo.stand (self);
			return;
		}

		M_MoveToGoal (self, dist);

		if (!FindTarget (self))
			return;
	}

	if (ai_checkattack (self, dist))
		return;

	if (self->monsterinfo.attack_state == AS_SLIDING)
	{
		ai_run_slide (self, dist);
		return;
	}

	if (enemy_vis)
	{
		M_MoveToGoal (self, dist);
		self->monsterinfo.aiflags &= ~AI_LOST_SIGHT;
		VectorCopy (self->enemy->s.origin, self->monsterinfo.last_sighting);
		self->monsterinfo.trail_time = level.time;
		return;
	}

#ifdef AI_FIXME
	// coop will change to another enemy if visible
	if (coop->integer)
	{	// FIXME: insane guys get mad with this, which causes crashes!
		if (FindTarget (self))
			return;
	}
#endif

	if ((self->monsterinfo.search_time) && (level.time > (self->monsterinfo.search_time + 20000)))
	{
		M_MoveToGoal (self, dist);
		self->monsterinfo.search_time = 0;
		return;
	}

	save = self->goalentity;
	tempgoal = G_Spawn();
	self->goalentity = tempgoal;

	newcourse = false;

	if (!(self->monsterinfo.aiflags & AI_LOST_SIGHT))
	{
		// just lost sight of the player, decide where to go first
		self->monsterinfo.aiflags |= (AI_LOST_SIGHT | AI_PURSUIT_LAST_SEEN);
		self->monsterinfo.aiflags &= ~(AI_PURSUE_NEXT | AI_PURSUE_TEMP);
		newcourse = true;
	}

	if (self->monsterinfo.aiflags & AI_PURSUE_NEXT)
	{
		self->monsterinfo.aiflags &= ~AI_PURSUE_NEXT;

		// give ourself more time since we got this far
		self->monsterinfo.search_time = level.time + 5000;

		if (self->monsterinfo.aiflags & AI_PURSUE_TEMP)
		{
			self->monsterinfo.aiflags &= ~AI_PURSUE_TEMP;
			marker = NULL;
			VectorCopy (self->monsterinfo.saved_goal, self->monsterinfo.last_sighting);
			newcourse = true;
		}
		else if (self->monsterinfo.aiflags & AI_PURSUIT_LAST_SEEN)
		{
			self->monsterinfo.aiflags &= ~AI_PURSUIT_LAST_SEEN;
			marker = G_PlayerTrail_PickFirst (self);
		}
		else
		{
			marker = G_PlayerTrail_PickNext (self);
		}

		if (marker)
		{
			VectorCopy (marker->s.origin, self->monsterinfo.last_sighting);
			self->monsterinfo.trail_time = marker->timeStamp;
			self->s.angles[YAW] = self->ideal_yaw = marker->s.angles[YAW];
			newcourse = true;
		}
	}

	VectorSubtract (self->s.origin, self->monsterinfo.last_sighting, v);
	d1 = VectorLength(v);
	if (d1 <= dist)
	{
		self->monsterinfo.aiflags |= AI_PURSUE_NEXT;
		dist = d1;
	}

	VectorCopy (self->monsterinfo.last_sighting, self->goalentity->s.origin);

	if (newcourse)
	{
		G_Trace (&tr, self->s.origin, self->r.mins, self->r.maxs, self->monsterinfo.last_sighting, self, MASK_PLAYERSOLID);
		if (tr.fraction < 1)
		{
			VectorSubtract (self->goalentity->s.origin, self->s.origin, v);
			d1 = VectorLength(v);
			center = tr.fraction;
			d2 = d1 * ((center+1)/2);
			self->s.angles[YAW] = self->ideal_yaw = vectoyaw(v);
			AngleVectors(self->s.angles, v_forward, v_right, NULL);

			VectorSet(v, d2, -16, 0);
			G_ProjectSource (self->s.origin, v, v_forward, v_right, left_target);
			G_Trace (&tr, self->s.origin, self->r.mins, self->r.maxs, left_target, self, MASK_PLAYERSOLID);
			left = tr.fraction;

			VectorSet(v, d2, 16, 0);
			G_ProjectSource (self->s.origin, v, v_forward, v_right, right_target);
			G_Trace (&tr, self->s.origin, self->r.mins, self->r.maxs, right_target, self, MASK_PLAYERSOLID);
			right = tr.fraction;

			center = (d1*center)/d2;
			if (left >= center && left > right)
			{
				if (left < 1)
				{
					VectorSet(v, d2 * left * 0.5, -16, 0);
					G_ProjectSource (self->s.origin, v, v_forward, v_right, left_target);
				}
				VectorCopy (self->monsterinfo.last_sighting, self->monsterinfo.saved_goal);
				self->monsterinfo.aiflags |= AI_PURSUE_TEMP;
				VectorCopy (left_target, self->goalentity->s.origin);
				VectorCopy (left_target, self->monsterinfo.last_sighting);
				VectorSubtract (self->goalentity->s.origin, self->s.origin, v);
				self->s.angles[YAW] = self->ideal_yaw = vectoyaw(v);
			}
			else if (right >= center && right > left)
			{
				if (right < 1)
				{
					VectorSet(v, d2 * right * 0.5, 16, 0);
					G_ProjectSource (self->s.origin, v, v_forward, v_right, right_target);
				}
				VectorCopy (self->monsterinfo.last_sighting, self->monsterinfo.saved_goal);
				self->monsterinfo.aiflags |= AI_PURSUE_TEMP;
				VectorCopy (right_target, self->goalentity->s.origin);
				VectorCopy (right_target, self->monsterinfo.last_sighting);
				VectorSubtract (self->goalentity->s.origin, self->s.origin, v);
				self->s.angles[YAW] = self->ideal_yaw = vectoyaw(v);
			}
		}
	}

	M_MoveToGoal (self, dist);

	G_FreeEdict(tempgoal);

	if (self)
		self->goalentity = save;
}
Example #14
0
/*
=============
ai_checkattack

Decides if we're going to attack or do something else
used by ai_run and ai_stand
=============
*/
bool ai_checkattack (edict_t *self, float dist)
{
	vec3_t		temp;
	bool	hesDeadJim;

// this causes monsters to run blindly to the combat point w/o firing
	if (self->goalentity)
	{
		if (self->monsterinfo.aiflags & AI_COMBAT_POINT)
			return false;

		if (self->monsterinfo.aiflags & AI_SOUND_TARGET)
		{
			if (level.time - self->enemy->teleport_time > 5000)
			{
				if (self->goalentity == self->enemy) {
					if (self->movetarget)
						self->goalentity = self->movetarget;
					else
						self->goalentity = NULL;
				}
				self->monsterinfo.aiflags &= ~AI_SOUND_TARGET;
				if (self->monsterinfo.aiflags & AI_TEMP_STAND_GROUND)
					self->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_TEMP_STAND_GROUND);
			}
			else
			{
				self->show_hostile = level.time + 1000;
				return false;
			}
		}
	}

	enemy_vis = false;

// see if the enemy is dead
	hesDeadJim = false;
	if ((!self->enemy) || (!self->enemy->r.inuse))
	{
		hesDeadJim = true;
	}
	else if (self->monsterinfo.aiflags & AI_MEDIC)
	{
		if (self->enemy->health > 0)
		{
			hesDeadJim = true;
			self->monsterinfo.aiflags &= ~AI_MEDIC;
		}
	}
	else
	{
		if (self->monsterinfo.aiflags & AI_BRUTAL)
		{
			if (self->enemy->health <= -80)
				hesDeadJim = true;
		}
		else
		{
			if (self->enemy->health <= 0)
				hesDeadJim = true;
		}
	}

	if (hesDeadJim)
	{
		self->enemy = NULL;
	// FIXME: look all around for other targets
		if (self->oldenemy && self->oldenemy->health > 0)
		{
			self->enemy = self->oldenemy;
			self->oldenemy = NULL;
			HuntTarget (self);
		}
		else
		{
			if (self->movetarget)
			{
				self->goalentity = self->movetarget;
				self->monsterinfo.walk (self);
			}
			else
			{
				// we need the pausetime otherwise the stand code
				// will just revert to walking with no target and
				// the monsters will wonder around aimlessly trying
				// to hunt the world entity
				self->monsterinfo.pausetime = level.time + 100000000;
				self->monsterinfo.stand (self);
			}
			return true;
		}
	}

	self->show_hostile = level.time + 1000;		// wake up other monsters

// check knowledge of enemy
	enemy_vis = G_Visible(self, self->enemy);
	if (enemy_vis)
	{
		self->monsterinfo.search_time = level.time + 5000;
		VectorCopy (self->enemy->s.origin, self->monsterinfo.last_sighting);
	}

// look for other coop players here
//	if (coop && self->monsterinfo.search_time < level.time)
//	{
//		if (FindTarget (self))
//			return true;
//	}

	enemy_infront = G_InFront(self, self->enemy);
	enemy_range = range(self, self->enemy);
	VectorSubtract (self->enemy->s.origin, self->s.origin, temp);
	enemy_yaw = vectoyaw(temp);


	// JDC self->ideal_yaw = enemy_yaw;

	if (self->monsterinfo.attack_state == AS_MISSILE)
	{
		ai_run_missile (self);
		return true;
	}
	if (self->monsterinfo.attack_state == AS_MELEE)
	{
		ai_run_melee (self);
		return true;
	}

	// if enemy is not currently visible, we will never attack
	if (!enemy_vis)
		return false;

	return self->monsterinfo.checkattack (self);
}
Example #15
0
File: m_medic.c Project: qbism/qbq2
void medic_NextPatrolPoint (edict_t *self, edict_t *hint)
{
	edict_t		*next=NULL;
	edict_t		*e;
	vec3_t		dir;
	qboolean	switch_paths=false;

	self->monsterinfo.aiflags &= ~AI_MEDIC_PATROL;

//	if(self->monsterinfo.aiflags & AI_MEDIC)
//		return;

	if(self->goalentity == hint)
		self->goalentity = NULL;
	if(self->movetarget == hint)
		self->movetarget = NULL;
	if (!(self->monsterinfo.aiflags & AI_MEDIC))
	{
		if(medic_FindDeadMonster(self))
			return;
	}
	if(self->monsterinfo.pathdir == 1)
	{
		if(hint->hint_chain)
			next = hint->hint_chain;
		else
		{
			self->monsterinfo.pathdir = -1;
			switch_paths = true;
		}
	}
	if(self->monsterinfo.pathdir == -1)
	{
		e = hint_chain_starts[hint->hint_chain_id];
		while(e)
		{
			if(e->hint_chain == hint)
			{
				next = e;
				break;
			}
			e = e->hint_chain;
		}
	}
	if(!next)
	{
		self->monsterinfo.pathdir = 1;
		next = hint->hint_chain;
		switch_paths = true;
	}
	// If switch_paths is true, we reached the end of a hint_chain. Just for grins,
	// search for *another* visible hint_path chain and use it if it's reasonably close
	if(switch_paths && hint_chain_count > 1)
	{
		edict_t	*e;
		edict_t	*alternate=NULL;
		float	dist;
		vec3_t	dir;
		int		i;
		float	bestdistance=512;

		for(i=game.maxclients+1; i<globals.num_edicts; i++)
		{
			e = &g_edicts[i];
			if(!e->inuse)
				continue;
			if(Q_strcasecmp(e->classname,"hint_path"))
				continue;
			if(next && (e->hint_chain_id == next->hint_chain_id))
				continue;
			if(!visible(self,e))
				continue;
			if(!canReach(self,e))
				continue;
			VectorSubtract(e->s.origin,self->s.origin,dir);
			dist = VectorLength(dir);
			if(dist < bestdistance)
			{
				alternate = e;
				bestdistance = dist;
			}
		}
		if(alternate)
			next = alternate;
	}
	if(next)
	{
		self->hint_chain_id = next->hint_chain_id;
		VectorSubtract(next->s.origin, self->s.origin, dir);
		self->ideal_yaw = vectoyaw(dir);
		self->goalentity = self->movetarget = next;
		self->monsterinfo.pausetime = 0;
		self->monsterinfo.aiflags |= AI_MEDIC_PATROL;
		self->monsterinfo.aiflags &= ~(AI_SOUND_TARGET | AI_PURSUIT_LAST_SEEN | AI_PURSUE_NEXT | AI_PURSUE_TEMP);
		// run for it
		self->monsterinfo.run (self);
	}
	else
	{
		self->monsterinfo.pausetime = level.time + 100000000;
		self->monsterinfo.stand (self);
	}
}
Example #16
0
qboolean Makron_CheckAttack (edict_t *self) {
	vec3_t	temp;
	float	chance;
	//qboolean	enemy_infront;
	int			enemy_range;
	float		enemy_yaw;

	if (!self->enemy)
		return false;
/*	if (self->enemy->health > 0) {
	// see if any entities are in the way of the shot
		VectorCopy (self->s.origin, spot1);
		spot1[2] += self->viewheight;
		VectorCopy (self->enemy->s.origin, spot2);
		spot2[2] += self->enemy->viewheight;

		tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA);

		// do we have a clear shot?
		if (tr.ent != self->enemy)
			return false;
	}
*/
	//enemy_infront = infront(self, self->enemy);
	enemy_range = range(self, self->enemy);
	VectorSubtract (self->enemy->s.origin, self->s.origin, temp);
	enemy_yaw = vectoyaw(temp);

	self->ideal_yaw = enemy_yaw;

	// melee attack
	if (enemy_range == RANGE_MELEE)
	{
		if (self->monsterinfo.melee)
			self->monsterinfo.attack_state = AS_MELEE;
		else
			self->monsterinfo.attack_state = AS_MISSILE;
		return true;
	}

// missile attack
	if (!self->monsterinfo.attack)
		return false;

	if (level.time < self->monsterinfo.attack_finished)
		return false;

//	if (enemy_range == RANGE_FAR)
//		return false;

	if (self->monsterinfo.aiflags & AI_STAND_GROUND) {
		chance = 0.6;
	} else if (enemy_range == RANGE_MELEE) {
		chance = 0.85;
	} else if (enemy_range == RANGE_NEAR) {
		chance = 0.6;
	} else if (enemy_range == RANGE_MID) {
		chance = 0.4;
	} else {
		chance = 0.2;
	}

	if (random () < chance) {
		self->monsterinfo.attack_state = AS_MISSILE;
		self->monsterinfo.attack_finished = level.time + 0.3*random();
		return true;
	}

	if (self->flags & FL_FLY) {
		if (random() < 0.3)
			self->monsterinfo.attack_state = AS_SLIDING;
		else
			self->monsterinfo.attack_state = AS_STRAIGHT;
	}

	return false;
}
Example #17
0
File: m_medic.c Project: qbism/qbq2
void medic_idle (edict_t *self)
{
	if(!(self->spawnflags & SF_MONSTER_AMBUSH))
		gi.sound (self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0);

	if(self->monsterinfo.aiflags & AI_MEDIC)
	{
		// Then we must have reached this point after losing sight
		// of our patient.
		abortHeal(self,false);
	}

	if(medic_FindDeadMonster(self))
		return;

	// If the map has hint_paths, AND the medic isn't at a HOLD point_combat,
	// AND the medic has previously called FoundTarget (trail_time set to
	// level.time), then look for hint_path chain and follow it, hopefully
	// to find monsters to resurrect
	if(self->monsterinfo.aiflags & AI_HINT_TEST)
		return;

	if (hint_chains_exist && !(self->monsterinfo.aiflags & AI_STAND_GROUND)
		&& ((self->monsterinfo.trail_time > 0) || medic_test) )
	{
		edict_t	*e;
		edict_t	*hint=NULL;
		float	dist;
		vec3_t	dir;
		int		i;
		float	bestdistance=99999;

		for(i=game.maxclients+1; i<globals.num_edicts; i++)
		{
			e = &g_edicts[i];
			if(!e->inuse)
				continue;
			if(Q_strcasecmp(e->classname,"hint_path"))
				continue;
			if(!visible(self,e))
				continue;
			if(!canReach(self,e))
				continue;
			VectorSubtract(e->s.origin,self->s.origin,dir);
			dist = VectorLength(dir);
			if(dist < bestdistance)
			{
				hint = e;
				bestdistance = dist;
			}
		}
		if(hint)
		{
			self->hint_chain_id = hint->hint_chain_id;
			if(!self->monsterinfo.pathdir)
				self->monsterinfo.pathdir = 1;
			VectorSubtract(hint->s.origin, self->s.origin, dir);
			self->ideal_yaw = vectoyaw(dir);
			self->goalentity = self->movetarget = hint;
			self->monsterinfo.pausetime = 0;
			self->monsterinfo.aiflags |= AI_MEDIC_PATROL;
			self->monsterinfo.aiflags &= ~(AI_SOUND_TARGET | AI_PURSUIT_LAST_SEEN | AI_PURSUE_NEXT | AI_PURSUE_TEMP);
			// run for it
			self->monsterinfo.run (self);
		}
	}
}
Example #18
0
int HintTestStart(edict_t *self)
{
    edict_t *e;
    edict_t *hint = NULL;
    float   dist;
    vec3_t  dir;
    int     i;
    float   bestdistance = 99999;

    if (!hint_chains_exist)
    {
        return 0;
    }

    for (i = game.maxclients + 1; i < globals.num_edicts; i++)
    {
        e = &g_edicts[i];
        if (!e->inuse)
        {
            continue;
        }
        if (Q_strcasecmp(e->classname, "hint_path"))
        {
            continue;
        }
        if (!visible(self, e))
        {
            continue;
        }
        if (!canReach(self, e))
        {
            continue;
        }
        VectorSubtract(e->s.origin, self->s.origin, dir);
        dist = VectorLength(dir);
        if (dist < bestdistance)
        {
            hint         = e;
            bestdistance = dist;
        }
    }
    if (hint)
    {
        self->hint_chain_id = hint->hint_chain_id;
        if (!self->monsterinfo.pathdir)
        {
            self->monsterinfo.pathdir = 1;
        }
        VectorSubtract(hint->s.origin, self->s.origin, dir);
        self->ideal_yaw             = vectoyaw(dir);
        self->enemy                 = self->oldenemy = NULL;
        self->goalentity            = self->movetarget = hint;
        self->monsterinfo.pausetime = 0;
        self->monsterinfo.aiflags   = AI_HINT_TEST;
        // run for it
        self->monsterinfo.run(self);
        return 1;
    }
    else
    {
        return -1;
    }
}
Example #19
0
/*
-------------------------
NAVNEW_SidestepBlocker
-------------------------
*/
qboolean NAVNEW_SidestepBlocker( gentity_t *self, gentity_t *blocker, vec3_t blocked_dir, float blocked_dist, vec3_t movedir, vec3_t right )
{//trace to sides of blocker and see if either is clear
	trace_t	tr;
	vec3_t	avoidAngles;
	vec3_t	avoidRight_dir, avoidLeft_dir, block_pos, mins;
	float	rightSucc, leftSucc, yaw, avoidRadius, arcAngle;

	VectorCopy( self->r.mins, mins );
	mins[2] += STEPSIZE;

	//Get the blocked direction
	yaw = vectoyaw( blocked_dir );

	//Get the avoid radius
	avoidRadius = sqrt( ( blocker->r.maxs[0] * blocker->r.maxs[0] ) + ( blocker->r.maxs[1] * blocker->r.maxs[1] ) ) + 
						sqrt( ( self->r.maxs[0] * self->r.maxs[0] ) + ( self->r.maxs[1] * self->r.maxs[1] ) );

	//See if we're inside our avoidance radius
	arcAngle = ( blocked_dist <= avoidRadius ) ? 135 : ( ( avoidRadius / blocked_dist ) * 90 );

	/*
	float dot = DotProduct( blocked_dir, right );

	//Go right on the first try if that works better
	if ( dot < 0.0f )
		arcAngle *= -1;
	*/

	VectorClear( avoidAngles );

	//need to stop it from ping-ponging, so we have a bit of a debounce time on which side you try
	if ( self->NPC->sideStepHoldTime > level.time )
	{
		if ( self->NPC->lastSideStepSide == -1 )//left
		{
			arcAngle *= -1;
		}//else right
		avoidAngles[YAW] = AngleNormalize360( yaw + arcAngle );
		AngleVectors( avoidAngles, movedir, NULL, NULL );
		VectorMA( self->r.currentOrigin, blocked_dist, movedir, block_pos );
		trap->Trace( &tr, self->r.currentOrigin, mins, self->r.maxs, block_pos, self->s.number, self->clipmask|CONTENTS_BOTCLIP, qfalse, 0, 0 );
		return (tr.fraction==1.0&&!tr.allsolid&&!tr.startsolid);
	}

	//test right
	avoidAngles[YAW] = AngleNormalize360( yaw + arcAngle );
	AngleVectors( avoidAngles, avoidRight_dir, NULL, NULL );

	VectorMA( self->r.currentOrigin, blocked_dist, avoidRight_dir, block_pos );
		
	trap->Trace( &tr, self->r.currentOrigin, mins, self->r.maxs, block_pos, self->s.number, self->clipmask|CONTENTS_BOTCLIP, qfalse, 0, 0 );

	if ( !tr.allsolid && !tr.startsolid )
	{
		if ( tr.fraction >= 1.0f )
		{//all clear, go for it (favor the right if both are equal)
			VectorCopy( avoidRight_dir, movedir );
			self->NPC->lastSideStepSide = 1;
			self->NPC->sideStepHoldTime = level.time + 2000;
			return qtrue;
		}
		rightSucc = tr.fraction;
	}
	else
	{
		rightSucc = 0.0f;
	}

	//now test left
	arcAngle *= -1;

	avoidAngles[YAW] = AngleNormalize360( yaw + arcAngle );
	AngleVectors( avoidAngles, avoidLeft_dir, NULL, NULL );

	VectorMA( self->r.currentOrigin, blocked_dist, avoidLeft_dir, block_pos );
		
	trap->Trace( &tr, self->r.currentOrigin, mins, self->r.maxs, block_pos, self->s.number, self->clipmask|CONTENTS_BOTCLIP, qfalse, 0, 0 );

	if ( !tr.allsolid && !tr.startsolid )
	{
		if ( tr.fraction >= 1.0f )
		{//all clear, go for it (right side would have already succeeded if as good as this)
			VectorCopy( avoidLeft_dir, movedir );
			self->NPC->lastSideStepSide = -1;
			self->NPC->sideStepHoldTime = level.time + 2000;
			return qtrue;
		}
		leftSucc = tr.fraction;
	}
	else
	{
		leftSucc = 0.0f;
	}

	if ( leftSucc == 0.0f && rightSucc == 0.0f )
	{//both sides failed
		return qfalse;
	}

	if ( rightSucc*blocked_dist >= avoidRadius || leftSucc*blocked_dist >= avoidRadius ) 
	{//the traces hit something, but got a relatively good distance
		if ( rightSucc >= leftSucc )
		{//favor the right, all things being equal
			VectorCopy( avoidRight_dir, movedir );
			self->NPC->lastSideStepSide = 1;
			self->NPC->sideStepHoldTime = level.time + 2000;
		}
		else
		{
			VectorCopy( avoidLeft_dir, movedir );
			self->NPC->lastSideStepSide = -1;
			self->NPC->sideStepHoldTime = level.time + 2000;
		}
		return qtrue;
	}

	//if neither are enough, we probably can't get around him
	return qfalse;
}
Example #20
0
qboolean Boss2_CheckAttack (edict_t *self)
{
	vec3_t	spot1, spot2;
	vec3_t	temp;
	float	chance;
	trace_t	tr;
	qboolean	enemy_infront;
	int			enemy_range;
	float		enemy_yaw;

	if (self->enemy->health > 0)
	{
	// see if any entities are in the way of the shot
		VectorCopy (self->s.origin, spot1);
		spot1[2] += self->viewheight;
		VectorCopy (self->enemy->s.origin, spot2);
		spot2[2] += self->enemy->viewheight;

		tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA);

		// do we have a clear shot?
		if (tr.ent != self->enemy)
		{	
			// PGM - we want them to go ahead and shoot at info_notnulls if they can.
			if(self->enemy->solid != SOLID_NOT || tr.fraction < 1.0)		//PGM
				return false;
		}
	}
	
	enemy_infront = infront(self, self->enemy);
	enemy_range = range(self, self->enemy);
	VectorSubtract (self->enemy->s.origin, self->s.origin, temp);
	enemy_yaw = vectoyaw(temp);

	self->ideal_yaw = enemy_yaw;


	// melee attack
	if (enemy_range == RANGE_MELEE)
	{
		if (self->monsterinfo.melee)
			self->monsterinfo.attack_state = AS_MELEE;
		else
			self->monsterinfo.attack_state = AS_MISSILE;
		return true;
	}
	
// missile attack
	if (!self->monsterinfo.attack)
		return false;
		
	if (level.time < self->monsterinfo.attack_finished)
		return false;
		
	if (enemy_range == RANGE_FAR)
		return false;

	if (self->monsterinfo.aiflags & AI_STAND_GROUND)
	{
		chance = 0.4;
	}
	else if (enemy_range == RANGE_MELEE)
	{
		chance = 0.8;
	}
	else if (enemy_range == RANGE_NEAR)
	{
		chance = 0.8;
	}
	else if (enemy_range == RANGE_MID)
	{
		chance = 0.8;
	}
	else
	{
		return false;
	}

	// PGM - go ahead and shoot every time if it's a info_notnull
	if ((random () < chance) || (self->enemy->solid == SOLID_NOT))
	{
		self->monsterinfo.attack_state = AS_MISSILE;
		self->monsterinfo.attack_finished = level.time + 2*random();
		return true;
	}

	if (self->flags & FL_FLY)
	{
		if (random() < 0.3)
			self->monsterinfo.attack_state = AS_SLIDING;
		else
			self->monsterinfo.attack_state = AS_STRAIGHT;
	}

	return false;
}
Example #21
0
void monster_start_go (edict_t *self)
{
	vec3_t	v;

	if (self->health <= 0)
		return;

	// check for target to combat_point and change to combattarget
	if (self->target)
	{
		qboolean	notcombat;
		qboolean	fixup;
		edict_t		*target;

		target = NULL;
		notcombat = false;
		fixup = false;
		while ((target = G_Find (target, FOFS(targetname), self->target)) != NULL)
		{
			if (strcmp(target->classname, "point_combat") == 0)
			{
				self->combattarget = self->target;
				fixup = true;
			}
			else
			{
				notcombat = true;
			}
		}
		if (notcombat && self->combattarget)
			gi.dprintf("%s at %s has target with mixed types\n", self->classname, vtos(self->s.origin));
		if (fixup)
			self->target = NULL;
	}

	// validate combattarget
	if (self->combattarget)
	{
		edict_t		*target;

		target = NULL;
		while ((target = G_Find (target, FOFS(targetname), self->combattarget)) != NULL)
		{
			if (strcmp(target->classname, "point_combat") != 0)
			{
				gi.dprintf("%s at (%i %i %i) has a bad combattarget %s : %s at (%i %i %i)\n",
					self->classname, (int)self->s.origin[0], (int)self->s.origin[1], (int)self->s.origin[2],
					self->combattarget, target->classname, (int)target->s.origin[0], (int)target->s.origin[1],
					(int)target->s.origin[2]);
			}
		}
	}

	if (self->target)
	{
		self->goalentity = self->movetarget = G_PickTarget(self->target);
		if (!self->movetarget)
		{
			gi.dprintf ("%s can't find target %s at %s\n", self->classname, self->target, vtos(self->s.origin));
			self->target = NULL;
			self->monsterinfo.pausetime = 100000000;
			self->monsterinfo.stand (self);
		}
		else if (strcmp (self->movetarget->classname, "path_corner") == 0)
		{
			VectorSubtract (self->goalentity->s.origin, self->s.origin, v);
			self->ideal_yaw = self->s.angles[YAW] = vectoyaw(v);
			self->monsterinfo.walk (self);
			self->target = NULL;
		}
		else
		{
			self->goalentity = self->movetarget = NULL;
			self->monsterinfo.pausetime = 100000000;
			self->monsterinfo.stand (self);
		}
	}
	else
	{
		self->monsterinfo.pausetime = 100000000;
		self->monsterinfo.stand (self);
	}

	self->think = monster_think;
	self->nextthink = level.time + FRAMETIME;
}
Example #22
0
File: p_hud.c Project: ZwS/qudos
/* ================== */
#define RANGE_1_METER    39	/* 1 meter in map unit */
void
CoopScoreboardMessage(edict_t * ent)
{
	gclient_t      *cl;
	edict_t        *cl_ent;
	char		string    [1400];
	int		health    , armor;
	int		i         , j, x, y;
	int		dist      , dir_h, dir_v;
	vec3_t		v;
	float		angle;
	char		szArrow   [8];

	string[0] = '\0';
	x = 160;
	y = 8;
	for (i = 0; i < game.maxclients; i++) {
		cl_ent = g_edicts + 1 + i;
		if (!cl_ent->inuse || game.clients[i].resp.spectator)
			continue;

		cl = &game.clients[i];

		health = max(cl_ent->health, 0);
		health = (min(health, 100) / 5) * 5;			/* bh0..5..10.. ..100 */
		armor = entArmor(cl_ent);
		armor = max(armor, 0);
		armor = (min(armor, 100) / 5) * 5;			/* ba0..5..10.. ..100 */

		j = strlen(string);
		if (cl_ent == ent) {					/* The player himself */
			Com_sprintf(string + j, sizeof(string) - j,
			    "xr -%i yt %i picn /players/%s_i.pcx "	/* face */
			    "xr -%i yt %i string2 \"%s\" "		/* name */
			    "xr -%i yt %i picn bh%i "			/* health */
			    "yt %i picn ba%i "				/* armor */
			    "xr -%i yt %i string2 \"%s\" ",		/* ping */
			    x, y, Info_ValueForKey(cl_ent->client->pers.userinfo, "skin"),
			    x - 34, y, cl_ent->client->pers.netname,
			    x - 35, y + 8, health,
			    y + 13, armor,
			    x - 82, y + 20, va("(%dms)", min(cl->ping, 999)));
		} else {
			VectorSubtract(cl_ent->s.origin, ent->s.origin, v);
			dist = (int)(VectorLength(v) / RANGE_1_METER);


			/* direction_V : up, down or same height */
			if (v[2] > 3 * RANGE_1_METER)
				dir_v = 1;
			else if (v[2] < -3 * RANGE_1_METER)
				dir_v = 2;
			else
				dir_v = 0;

			/* direction_H : left, right, front or back */
			if (fabs(v[0]) < RANGE_1_METER && fabs(v[1]) < RANGE_1_METER)
				dir_h = 0;	/* Too near, no direction */
			else {
				angle = vectoyaw(v) - ent->s.angles[YAW];
				if (angle < 0)
					angle += 360;
				else if (angle >= 360)
					angle -= 360;

				if (angle < 45)
					dir_h = 1;	/* front */
				else if (angle < 135)
					dir_h = 2;	/* left */
				else if (angle < 225)
					dir_h = 3;	/* back */
				else if (angle < 315)
					dir_h = 4;	/* right */
				else
					dir_h = 1;	/* front */
			}

			Com_sprintf(szArrow, sizeof(szArrow), "v%ih%i", dir_v, dir_h);
			Com_sprintf(string + j, sizeof(string) - j,
			    "xr -%i yt %i picn /players/%s_i.pcx "	/* face */
			    "xr -%i yt %i string \"%s\" "		/* name */
			    "xr -%i yt %i picn bh%i "			/* health */
			    "yt %i picn ba%i "				/* armor */
			    "yt %i picn %s "				/* directional arrow */
			    "xr -%i string \"%im (%dms)\" ",		/* distance + ping */
			    x, y, Info_ValueForKey(cl_ent->client->pers.userinfo, "skin"),
			    x - 34, y, cl_ent->client->pers.netname,
			    x - 35, y + 8, health,
			    y + 13, armor,
			    y + 20, szArrow,
			    x - 62, dist, min(cl->ping, 999));
		}
		x += 160;
	}

	if (string[0]) {
		gi.WriteByte(svc_layout);
		gi.WriteString(string);
	}
}