コード例 #1
0
void CCarrier::SpawnMonsters ()
{
	vec3f offset (105, 0, -58); // real distance needed is (sqrt (56*56*2) + sqrt(16*16*2)) or 101.8
	anglef angles = Entity->State.GetAngles().ToVectors ();

	vec3f startpoint;
	G_ProjectSource (Entity->State.GetOrigin(), offset, angles, startpoint);

	// the +0.1 is because level.time is sometimes a little low
	FrameNumber mytime = ((Level.Frame + 1 - FrameCalc) / 5);

	vec3f spawnpoint;
	if (FindSpawnPoint (startpoint, flyer_mins, flyer_maxs, spawnpoint, 32))
	{
		CMonsterEntity *ent = NULL;

		// the second flier should be a kamikaze flyer
		if (mytime != 2)
			ent = CreateMonster (spawnpoint, Entity->State.GetAngles(), "monster_flyer");
		else
			ent = CreateMonster (spawnpoint, Entity->State.GetAngles(), "monster_kamikaze");

		if (!ent)
			return;

		Entity->PlaySound (CHAN_BODY, Sounds[SOUND_SPAWN]);

		MonsterSlots--;

		ent->NextThink = Level.Frame;
		void	(IMonster::*TheThink) () = ent->Monster->Think;
		(ent->Monster->*TheThink) ();
		
		ent->Monster->AIFlags |= AI_SPAWNED_CARRIER|AI_DO_NOT_COUNT|AI_IGNORE_SHOTS;
		ent->Monster->Commander = Entity;

		if ((Entity->Enemy->GetInUse()) && (entity_cast<IHurtableEntity>(*Entity->Enemy)->Health > 0))
		{
			ent->Enemy = Entity->Enemy;
			ent->Monster->FoundTarget ();
			if (mytime == 1)
			{
				ent->Monster->Lefty = false;
				ent->Monster->AttackState = AS_SLIDING;
				ent->Monster->CurrentMove = &FlyerMoveAttack2;
			}
			else if (mytime == 2)
			{
				ent->Monster->Lefty = false;
				ent->Monster->AttackState = AS_STRAIGHT;
				ent->Monster->CurrentMove = &FlyerMoveKamikaze;
				ent->Monster->AIFlags |= AI_CHARGING;
			}
			else if (mytime == 3)
			{
				ent->Monster->Lefty = true;
				ent->Monster->AttackState = AS_SLIDING;
				ent->Monster->CurrentMove = &FlyerMoveAttack2;
			}
		}
	}
}
コード例 #2
0
ファイル: m_medic.c プロジェクト: Izhido/qrevpak
void medic_cable_attack (edict_t *self)
{
	vec3_t	offset, start, end, f, r;
	trace_t	tr;
	vec3_t	dir, angles;
	float	distance;

	if (!self->enemy->inuse)
		return;

	AngleVectors (self->s.angles, f, r, NULL);
	VectorCopy (medic_cable_offsets[self->s.frame - FRAME_attack42], offset);
	G_ProjectSource (self->s.origin, offset, f, r, start);

	// check for max distance
	VectorSubtract (start, self->enemy->s.origin, dir);
	distance = VectorLength(dir);
	if (distance > 256)
		return;

	// check for min/max pitch
	vectoangles (dir, angles);
	if (angles[0] < -180)
		angles[0] += 360;
	if (fabs(angles[0]) > 45)
		return;

	tr = gi.trace (start, NULL, NULL, self->enemy->s.origin, self, MASK_SHOT);
	if (tr.fraction != 1.0 && tr.ent != self->enemy)
		return;

	if (self->s.frame == FRAME_attack43)
	{
		gi.sound (self->enemy, CHAN_AUTO, sound_hook_hit, 1, ATTN_NORM, 0);
		self->enemy->monsterinfo.aiflags |= AI_RESURRECTING;
	}
	else if (self->s.frame == FRAME_attack50)
	{
		self->enemy->spawnflags = 0;
		self->enemy->monsterinfo.aiflags = 0;
		self->enemy->target = NULL;
		self->enemy->targetname = NULL;
		self->enemy->combattarget = NULL;
		self->enemy->deathtarget = NULL;
		self->enemy->owner = self;
		ED_CallSpawn (self->enemy);
		self->enemy->owner = NULL;
		if (self->enemy->think)
		{
			self->enemy->nextthink = level.time;
			self->enemy->think (self->enemy);
		}
		self->enemy->monsterinfo.aiflags |= AI_RESURRECTING;
		if (self->oldenemy && self->oldenemy->client)
		{
			self->enemy->enemy = self->oldenemy;
			FoundTarget (self->enemy);
		}
	}
	else
	{
		if (self->s.frame == FRAME_attack44)
			gi.sound (self, CHAN_WEAPON, sound_hook_heal, 1, ATTN_NORM, 0);
	}

	// adjust start for beam origin being in middle of a segment
	VectorMA (start, 8, f, start);

	// adjust end z for end spot since the monster is currently dead
	VectorCopy (self->enemy->s.origin, end);
	end[2] = self->enemy->absmin[2] + self->enemy->size[2] / 2;

	gi.WriteByte (svc_temp_entity);
	gi.WriteByte (TE_MEDIC_CABLE_ATTACK);
	gi.WriteShort (self - g_edicts);
	gi.WritePosition (start);
	gi.WritePosition (end);
	gi.multicast (self->s.origin, MULTICAST_PVS);
}
コード例 #3
0
ファイル: gunner.c プロジェクト: DrItanium/rogue
void GunnerGrenade (edict_t *self)
{
	vec3_t	start;
	vec3_t	forward, right, up;
	vec3_t	aim;
	int		flash_number;
	float	spread;
	float	pitch = 0;
	// PMM
	vec3_t	target;	
	qboolean blindfire = false;

	if(!self->enemy || !self->enemy->inuse)		//PGM
		return;									//PGM

	// pmm
	if (self->monsterinfo.aiflags & AI_MANUAL_STEERING)
		blindfire = true;

	if (self->s.frame == FRAME_attak105)
	{
		spread = .02;
		flash_number = MZ2_GUNNER_GRENADE_1;
	}
	else if (self->s.frame == FRAME_attak108)
	{
		spread = .05;
		flash_number = MZ2_GUNNER_GRENADE_2;
	}
	else if (self->s.frame == FRAME_attak111)
	{
		spread = .08;
		flash_number = MZ2_GUNNER_GRENADE_3;
	}
	else // (self->s.frame == FRAME_attak114)
	{
		self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING;
		spread = .11;
		flash_number = MZ2_GUNNER_GRENADE_4;
	}

	//	pmm
	// if we're shooting blind and we still can't see our enemy
	if ((blindfire) && (!visible(self, self->enemy)))
	{
		// and we have a valid blind_fire_target
		if (VectorCompare (self->monsterinfo.blind_fire_target, vec3_origin))
			return;
		
		VectorCopy (self->monsterinfo.blind_fire_target, target);
	}
	else
		VectorCopy (self->s.origin, target);
	// pmm

	AngleVectors (self->s.angles, forward, right, up);	//PGM
	G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);

	//PGM
	if(self->enemy)
	{
		float	dist;

		VectorSubtract(target, self->s.origin, aim);
		dist = VectorLength(aim);

		// aim up if they're on the same level as me and far away.
		if((dist > 512) && (aim[2] < 64) && (aim[2] > -64))
		{
			aim[2] += (dist - 512);
		}

		VectorNormalize (aim);
		pitch = aim[2];
		if(pitch > 0.4)
		{
			pitch = 0.4;
		}
		else if(pitch < -0.5)
			pitch = -0.5;
	}
	//PGM

	VectorMA (forward, spread, right, aim);
	VectorMA (aim, pitch, up, aim);

	monster_fire_grenade (self, start, aim, 50, 600, flash_number);
}
コード例 #4
0
ファイル: m_medic.c プロジェクト: Nephatrine/nephq2-game
qboolean medic_checkattack (edict_t *self)
{
	if (!(self->monsterinfo.aiflags & AI_MEDIC))
	{
		if( medic_FindDeadMonster(self) )
			return false;
	}

	if (self->monsterinfo.aiflags & AI_MEDIC)
	{
		float	r;
		vec3_t	forward, right, offset, start;
		trace_t	tr;

		// if we have 5 seconds or less before a timeout,
		// look for a hint_path to the target
		if ( (self->timestamp < level.time + 5) &&
			 (self->monsterinfo.last_hint_time + 5 < level.time) )
		{
			// check for hint_paths.
			self->monsterinfo.last_hint_time = level.time;
			if (hintcheck_monsterlost(self))
			{
				if(developer->value)
					gi.dprintf("medic at %s using hint_paths to find %s\n",
					vtos(self->s.origin), self->enemy->classname);
				self->timestamp = level.time + MEDIC_TRY_TIME;
				return false;
			}
		}

		// if we ran out of time, give up
		if (self->timestamp < level.time)
		{
			//if(developer->value)
			//	gi.dprintf("medic at %s timed out, abort heal\n",vtos(self->s.origin));
			abortHeal (self, true);
			self->timestamp = 0;
			return false;
		}
		
		// if our target went away
		if ((!self->enemy) || (!self->enemy->inuse)) {
			abortHeal (self,false);
			return false;
		}
		// if target is embedded in a solid
		if (embedded(self->enemy))
		{
			abortHeal (self,false);
			return false;
		}
		r = realrange(self,self->enemy);
		if (r > MEDIC_MAX_HEAL_DISTANCE+10) {
			self->monsterinfo.attack_state = AS_STRAIGHT;
			//abortHeal(self,false);
			return false;
		} else if(r < MEDIC_MIN_DISTANCE) {
			abortHeal(self,false);
			return false;
		}
		// Lazarus 1.6.2.3: if point-to-point vector from cable to
		// target is blocked by a solid
		AngleVectors (self->s.angles, forward, right, NULL);
		// Offset [8] has the largest displacement to the left... not a sure
		// thing but this one should be the most severe test.
		VectorCopy (medic_cable_offsets[8], offset);
		G_ProjectSource (self->s.origin, offset, forward, right, start);
		tr = gi.trace(start,NULL,NULL,self->enemy->s.origin,self,MASK_SHOT|MASK_WATER);
		if (tr.fraction < 1.0 && tr.ent != self->enemy)
			return false;
		medic_attack(self);
		return true;
	}

	// Lazarus: NEVER attack other monsters
	if ((self->enemy) && (self->enemy->svflags & SVF_MONSTER))
	{
		self->enemy = self->oldenemy;
		self->oldenemy = NULL;
		if(self->enemy && self->enemy->inuse)
		{
			if(visible(self,self->enemy))
				FoundTarget(self);
			else
				HuntTarget(self);
		}
		return false;
	}

	return M_CheckAttack (self);
}
コード例 #5
0
ファイル: m_medic.c プロジェクト: Nephatrine/nephq2-game
void medic_cable_attack (edict_t *self)
{
	vec3_t	offset, start, end, f, r;
	trace_t	tr;
	vec3_t	dir;
	float	distance;

	if ((!self->enemy) || (!self->enemy->inuse) || (self->enemy->svflags & SVF_GIB))
	{
		//gi.dprintf ("medic_cable_attack: aborting heal due to target being removed or gibbed\n");
		abortHeal (self,false);
		return;
	}

	//Knightmare- don't heal insanes or actors or critters
	if (!strcmp (self->enemy->classname, "misc_insane") || !strcmp (self->enemy->classname, "misc_actor")
		|| !strcmp (self->enemy->classname, "monster_mutant") || !strcmp (self->enemy->classname, "monster_flipper")) 
	{
		//gi.dprintf ("medic_cable_attack: not healing insane or actor or critter\n");
		abortHeal (self, true);
		return;
	}

	// Lazarus: check embeddment
	if (embedded(self->enemy))
	{
		//gi.dprintf ("medic_cable_attack: dead monster embedded in solid, aborting heal\n");
		abortHeal (self,false);
		return;
	}

	// see if our enemy has changed to a client, or our target has more than 0 health,
	// abort it .. we got switched to someone else due to damage
	if ((self->enemy->client) || (self->enemy->health > 0))
	{
		//gi.dprintf ("medic_cable_attack: aborting heal due to target health > 0 or client\n");
		abortHeal (self,false);
		return;
	}

	AngleVectors (self->s.angles, f, r, NULL);
	VectorCopy (medic_cable_offsets[self->s.frame - FRAME_attack42], offset);
	G_ProjectSource (self->s.origin, offset, f, r, start);

	// check for max distance
	// Lazarus: Not needed, done in checkattack
	// check for min distance
	VectorSubtract (self->enemy->s.origin, start, dir);
	distance = VectorLength(dir);
	if (distance < MEDIC_MIN_DISTANCE)
	{
		//gi.dprintf("medic_cable_attack: MEDIC_MIN_DISTANCE\n");
		abortHeal (self,false);
		return;
	}

	// Lazarus: Check for enemy behind muzzle... don't do these guys, 'cause usually this
	// results in monster entanglement
	VectorNormalize(dir);
	if(DotProduct(dir,f) < 0.)
	{
		//gi.dprintf ("medic_cable_attack: aborting heal due to possible entanglment\n");
		abortHeal (self,false);
		return;
	}

	// check for min/max pitch
	// Rogue takes this out... makes medic more likely to heal and 
	// comments say "doesn't look bad when it fails"... we'll see
/*	vectoangles (dir, angles);
	if (angles[0] < -180)
		angles[0] += 360;
	if (fabs(angles[0]) > 45)
		return; */

	tr = gi.trace (start, NULL, NULL, self->enemy->s.origin, self, MASK_SHOT);
	if (tr.fraction != 1.0 && tr.ent != self->enemy)
	{
		if (tr.ent == world)
		{
			// give up on second try
			if (self->monsterinfo.medicTries > 1)
			{
				abortHeal (self,true);
				return;
			}
			self->monsterinfo.medicTries++;
			cleanupHeal (self, 1);
			return;
		}
		abortHeal (self,false);
		return;
	}

	if (self->s.frame == FRAME_attack43)
	{
		gi.sound (self->enemy, CHAN_AUTO, sound_hook_hit, 1, ATTN_NORM, 0);
		self->enemy->monsterinfo.aiflags |= AI_RESURRECTING;
		M_SetEffects(self->enemy);
	}
	else if (self->s.frame == FRAME_attack50)
	{
		self->enemy->spawnflags &= SF_MONSTER_NOGIB;
		self->enemy->monsterinfo.aiflags = 0;
		self->enemy->target = NULL;
		self->enemy->targetname = NULL;
		self->enemy->combattarget = NULL;
		self->enemy->deathtarget = NULL;
		self->enemy->owner = self;
		// Lazarus: reset initially dead monsters to use the INVERSE of their
		// initial health, and force gib_health to default value
		if(self->enemy->max_health < 0)
		{
			self->enemy->max_health = -self->enemy->max_health;
			self->enemy->gib_health = 0;
		}
		self->enemy->health = self->enemy->max_health;
		self->enemy->takedamage = DAMAGE_AIM;
		self->enemy->flags &= ~FL_NO_KNOCKBACK;
		self->enemy->pain_debounce_time = 0;
		self->enemy->damage_debounce_time = 0;
		self->enemy->deadflag = DEAD_NO;
		if(self->enemy->s.effects & EF_FLIES)
			M_FliesOff(self->enemy);
		ED_CallSpawn (self->enemy);
		self->enemy->monsterinfo.healer = NULL;
		self->enemy->owner = NULL;

		// Knightmare- disable deadmonster_think
		if (self->enemy->postthink)
			self->enemy->postthink = NULL;

		if (self->enemy->think)
		{
			self->enemy->nextthink = level.time;
			self->enemy->think (self->enemy);
		}
		self->enemy->monsterinfo.aiflags &= ~AI_RESURRECTING;
		M_SetEffects(self->enemy);
		if (self->oldenemy && self->oldenemy->client)
		{
			self->enemy->enemy = self->oldenemy;
			FoundTarget (self->enemy);
		}
		else
		{
			// Lazarus: this should make oblivious monsters 
			// find player again
			self->enemy->enemy = NULL;
		}
	}
	else
	{
		if (self->s.frame == FRAME_attack44)
			gi.sound (self, CHAN_WEAPON, sound_hook_heal, 1, ATTN_NORM, 0);
	}

	// adjust start for beam origin being in middle of a segment
	// Lazarus: This isn't right... this causes cable start point to be well above muzzle
	//          when target is closeby. f should be vector from muzzle to target, not
	//          the forward viewing direction. PLUS... 8 isn't right... the model is
	//          actually 32 units long, so use 16.. fixed below.
//	VectorMA (start, 8, f, start);

	//Knightmare- if enemy went away, like after returning from another level, return
	if (!self->enemy)
		return;

	// adjust end z for end spot since the monster is currently dead
	VectorCopy (self->enemy->s.origin, end);
	end[2] = self->enemy->absmin[2] + self->enemy->size[2] / 2;

	// Lazarus fix
	VectorSubtract(end,start,f);
	VectorNormalize(f);
	VectorMA(start,16,f,start);

	gi.WriteByte (svc_temp_entity);
	gi.WriteByte (TE_MEDIC_CABLE_ATTACK);
	gi.WriteShort (self - g_edicts);
	gi.WritePosition (start);
	gi.WritePosition (end);
	gi.multicast (self->s.origin, MULTICAST_PVS);
}
コード例 #6
0
ファイル: Bitch.cpp プロジェクト: qbism/cleancodequake2
void CMaiden::Rocket ()
{
	if (!HasValidEnemy())
		return;

#if ROGUE_FEATURES
	vec3f	start, dir, vec, target;
	bool blindfire = (AIFlags & AI_MANUAL_STEERING) ? true : false;

	anglef angles = Entity->State.GetAngles().ToVectors ();
	G_ProjectSource (Entity->State.GetOrigin(), MonsterFlashOffsets[MZ2_CHICK_ROCKET_1], angles, start);

	sint32 rocketSpeed = 500 + (100 * CvarList[CV_SKILL].Integer());	// PGM rock & roll.... :)

	target = (blindfire) ? BlindFireTarget : Entity->Enemy->State.GetOrigin();
	if (blindfire)
	{
		vec = target;
		dir = vec - start;
	}
	// pmm
	// don't shoot at feet if they're above where i'm shooting from.
	else if(frand() < 0.33 || (start[2] < Entity->Enemy->GetAbsMin().Z))
	{
		vec = target;
		vec.Z += Entity->Enemy->ViewHeight;
		dir = vec - start;
	}
	else
	{
		vec = target;
		vec.Z = Entity->Enemy->GetAbsMin().Z;
		dir = vec - start;
	}

	// Lead target  (not when blindfiring)
	// 20, 35, 50, 65 chance of leading
	if((!blindfire) && ((frand() < (0.2 + ((3 - CvarList[CV_SKILL].Integer()) * 0.15)))))
	{
		vec = vec.MultiplyAngles (dir.Length() / rocketSpeed, entity_cast<IPhysicsEntity>(*Entity->Enemy)->Velocity);
		dir = vec - start;
	}

	dir.Normalize ();

	// pmm blindfire doesn't check target (done in checkattack)
	// paranoia, make sure we're not shooting a target right next to us
	CTrace trace (start, vec, Entity, CONTENTS_MASK_SHOT);
	if (blindfire)
	{
		// blindfire has different fail criteria for the trace
		if (!(trace.StartSolid || trace.AllSolid || (trace.Fraction < 0.5f)))
			MonsterFireRocket (start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1);
		else 
		{
			// geez, this is bad.  she's avoiding about 80% of her blindfires due to hitting things.
			// hunt around for a good shot
			// try shifting the target to the left a little (to help counter her large offset)
			vec = target;
			vec = vec.MultiplyAngles (-10, angles.Right);
			dir = vec - start;
			dir.NormalizeFast();
			trace (start, vec, Entity, CONTENTS_MASK_SHOT);
			if (!(trace.StartSolid || trace.AllSolid || (trace.Fraction < 0.5)))
				MonsterFireRocket (start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1);
			else 
			{
				// ok, that failed.  try to the right
				vec = target;
				vec = vec.MultiplyAngles (10, angles.Right);
				dir = vec - start;
				dir.NormalizeFast();
				trace (start, vec, Entity, CONTENTS_MASK_SHOT);
				if (!(trace.StartSolid || trace.AllSolid || (trace.Fraction < 0.5)))
					MonsterFireRocket (start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1);
			}
		}
	}
	else
		MonsterFireRocket (start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1);
#else
	vec3f	start, dir, vec;

	anglef angles = Entity->State.GetAngles().ToVectors ();
	G_ProjectSource (Entity->State.GetOrigin(), MonsterFlashOffsets[MZ2_CHICK_ROCKET_1], angles, start);

	vec = Entity->Enemy->State.GetOrigin();
	vec.Z += Entity->Enemy->ViewHeight;
	dir = vec - start;
	dir.NormalizeFast ();

	MonsterFireRocket (start, dir, 50, 500, MZ2_CHICK_ROCKET_1);
#endif
}	
コード例 #7
0
void soldier_fire (edict_t *self, int flash_number)
{
	vec3_t	start;
	vec3_t	forward, right, up;
	vec3_t	aim;
	vec3_t	dir;
	vec3_t	end;
	float	r, u;
	int		flash_index;

	if ((self->s.skinnum % 6) < 2)
		flash_index = blaster_flash[flash_number];
	else if ((self->s.skinnum % 6) < 4)
		flash_index = shotgun_flash[flash_number];
	else
		flash_index = machinegun_flash[flash_number];

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[flash_index], forward, right, start);

	if (flash_number == 5 || flash_number == 6)
	{
		VectorCopy (forward, aim);
	}
	else
	{
		VectorCopy (self->enemy->s.origin, end);
		end[2] += self->enemy->viewheight;

		// Lazarus fog reduction of accuracy
		if(self->monsterinfo.visibility < FOG_CANSEEGOOD)
		{
			end[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
			end[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
			end[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
		}
		
		VectorSubtract (end, start, aim);
		// Lazarus: Accuracy is skill level dependent
		if(skill->value < 3)
		{
			vectoangles (aim, dir);
			AngleVectors (dir, forward, right, up);

			r = crandom()*(1000 - 333*skill->value);
			u = crandom()*(500 - 167*skill->value);
			VectorMA (start, 8192, forward, end);
			VectorMA (end, r, right, end);
			VectorMA (end, u, up, end);

			VectorSubtract (end, start, aim);
		}
		VectorNormalize (aim);
	}

	if ((self->s.skinnum % 6) <= 1)
	{
		// Lazarus: make bolt speed skill level dependent
		monster_fire_blaster (self, start, aim, 5, 600 + 100*skill->value, flash_index, EF_BLASTER, BLASTER_ORANGE);
	}
	else if ((self->s.skinnum % 6) <= 3)
	{
		monster_fire_shotgun (self, start, aim, 2, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index);
	}
	else
	{
		if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME))
			self->monsterinfo.pausetime = level.time + (3 + rand() % 8) * FRAMETIME;

		monster_fire_bullet (self, start, aim, 2, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index);

		if (level.time >= self->monsterinfo.pausetime)
			self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
		else
			self->monsterinfo.aiflags |= AI_HOLD_FRAME;
	}
}
コード例 #8
0
ファイル: acebot_movement.c プロジェクト: basecq/q2dos
///////////////////////////////////////////////////////////////////////
// Checks for obstructions in front of bot
//
// This is a function I created origianlly for ACE that
// tries to help steer the bot around obstructions.
//
// If the move is resolved here, this function returns true.
///////////////////////////////////////////////////////////////////////
qboolean ACEMV_CheckEyes(edict_t *self, usercmd_t *ucmd)
{
	vec3_t  forward, right;
	vec3_t  leftstart, rightstart,focalpoint;
	vec3_t  upstart,upend;
	vec3_t  dir,offset;

	trace_t traceRight,traceLeft,traceUp, traceFront; // for eyesight

	// Get current angle and set up "eyes"
	VectorCopy(self->s.angles,dir);
	AngleVectors (dir, forward, right, NULL);
	
	// Let them move to targets by walls
	if(!self->movetarget)
		VectorSet(offset,200,0,4); // focalpoint 
	else
		VectorSet(offset,36,0,4); // focalpoint 
	
	G_ProjectSource (self->s.origin, offset, forward, right, focalpoint);

	// Check from self to focalpoint
	// Ladder code
	VectorSet(offset,36,0,0); // set as high as possible
	G_ProjectSource (self->s.origin, offset, forward, right, upend);
	traceFront = gi.trace(self->s.origin, self->mins, self->maxs, upend, self, MASK_OPAQUE);
		
	if(traceFront.contents & 0x8000000) // using detail brush here cuz sometimes it does not pick up ladders...??
	{
		ucmd->upmove = 400;
		ucmd->forwardmove = 400;
		return true;
	}
	
	// If this check fails we need to continue on with more detailed checks
	if(traceFront.fraction == 1)
	{	
		ucmd->forwardmove = 400;
		return true;
	}

	VectorSet(offset, 0, 18, 4);
	G_ProjectSource (self->s.origin, offset, forward, right, leftstart);
	
	offset[1] -= 36; // want to make sure this is correct
	//VectorSet(offset, 0, -18, 4);
	G_ProjectSource (self->s.origin, offset, forward, right, rightstart);

	traceRight = gi.trace(rightstart, NULL, NULL, focalpoint, self, MASK_OPAQUE);
	traceLeft = gi.trace(leftstart, NULL, NULL, focalpoint, self, MASK_OPAQUE);

	// Wall checking code, this will degenerate progressivly so the least cost 
	// check will be done first.
		
	// If open space move ok
	if(traceRight.fraction != 1 || traceLeft.fraction != 1 || strcmp(traceLeft.ent->classname,"func_door")!=0)
	{
		// Special uppoint logic to check for slopes/stairs/jumping etc.
		VectorSet(offset, 0, 18, 24);
		G_ProjectSource (self->s.origin, offset, forward, right, upstart);

		VectorSet(offset,0,0,200); // scan for height above head
		G_ProjectSource (self->s.origin, offset, forward, right, upend);
		traceUp = gi.trace(upstart, NULL, NULL, upend, self, MASK_OPAQUE);
			
		VectorSet(offset,200,0,200*traceUp.fraction-5); // set as high as possible
		G_ProjectSource (self->s.origin, offset, forward, right, upend);
		traceUp = gi.trace(upstart, NULL, NULL, upend, self, MASK_OPAQUE);

		// If the upper trace is not open, we need to turn.
		if(traceUp.fraction != 1)
		{						
			if(traceRight.fraction > traceLeft.fraction)
				self->s.angles[YAW] += (1.0 - traceLeft.fraction) * 45.0;
			else
				self->s.angles[YAW] += -(1.0 - traceRight.fraction) * 45.0;
			
			ucmd->forwardmove = 400;
			return true;
		}
	}
				
	return false;
}
コード例 #9
0
ファイル: m_soldier.c プロジェクト: MaddTheSane/Quake2
void soldier_fire (edict_t *self, int flash_number)
{
	vec3_t	start;
	vec3_t	forward, right, up;
	vec3_t	aim;
	vec3_t	dir;
	vec3_t	end;
	float	r, u;
	int		flash_index;

	if (self->s.skinnum < 2)
		flash_index = blaster_flash[flash_number];
	else if (self->s.skinnum < 4)
		flash_index = shotgun_flash[flash_number];
	else
		flash_index = machinegun_flash[flash_number];

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[flash_index], forward, right, start);

	if (flash_number == 5 || flash_number == 6)
	{
		VectorCopy (forward, aim);
	}
	else
	{
		VectorCopy (self->enemy->s.origin, end);
		end[2] += self->enemy->viewheight;
		VectorSubtract (end, start, aim);
		vectoangles (aim, dir);
		AngleVectors (dir, forward, right, up);

		r = crandom()*1000;
		u = crandom()*500;
		VectorMA (start, 8192, forward, end);
		VectorMA (end, r, right, end);
		VectorMA (end, u, up, end);

		VectorSubtract (end, start, aim);
		VectorNormalize (aim);
	}

	if (self->s.skinnum <= 1)
	{
		monster_fire_blaster (self, start, aim, 5, 600, flash_index, EF_BLASTER);
	}
	else if (self->s.skinnum <= 3)
	{
		monster_fire_shotgun (self, start, aim, 2, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index);
	}
	else
	{
		if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME))
			self->monsterinfo.pausetime = level.time + (3 + rand() % 8) * FRAMETIME;

		monster_fire_bullet (self, start, aim, 2, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index);

		if (level.time >= self->monsterinfo.pausetime)
			self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
		else
			self->monsterinfo.aiflags |= AI_HOLD_FRAME;
	}
}
コード例 #10
0
ファイル: m_tank.c プロジェクト: n1ckn4m3/kmquake2megacoop
void TankRocket (edict_t *self)
{
	trace_t	trace;
	vec3_t	forward, right;
	vec3_t	start;
	vec3_t	dir;
	vec3_t	vec;
	int		flash_number;
	// Lazarus: Added skill level-dependent rocket speed similar to Rogue pack
	int		rocketSpeed;

	// check if enemy went away
	if (!self->enemy || !self->enemy->inuse)
		return;

	if (self->s.frame == FRAME_attak324)
		flash_number = MZ2_TANK_ROCKET_1;
	else if (self->s.frame == FRAME_attak327)
		flash_number = MZ2_TANK_ROCKET_2;
	else // (self->s.frame == FRAME_attak330)
		flash_number = MZ2_TANK_ROCKET_3;

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);

	if((self->spawnflags & SF_MONSTER_SPECIAL))
		rocketSpeed = 400; // Lazarus: Homing rockets are tougher if slow
	else
		rocketSpeed = 500 + (100 * skill->value);

/*	VectorCopy (self->enemy->s.origin, vec);
	vec[2] += self->enemy->viewheight;
	VectorSubtract (vec, start, dir);
	VectorNormalize (dir); */
	// Lazarus: Added homers
	VectorCopy (self->enemy->s.origin, vec);
	if(random() < 0.66 || (start[2] < self->enemy->absmin[2]))
	{
//		gi.dprintf("normal shot\n");
		vec[2] += self->enemy->viewheight;
	}
	else
	{
//		gi.dprintf("shooting at feet!\n");
		vec[2] = self->enemy->absmin[2];
	}

	// Lazarus fog reduction of accuracy
	if(self->monsterinfo.visibility < FOG_CANSEEGOOD)
	{
		vec[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
		vec[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
		vec[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
	}

	VectorSubtract (vec, start, dir);
	// lead target, but not if using homers
	// 20, 35, 50, 65 chance of leading
	// Lazarus: Switched this around from Rogue code... it led target more often
	//          for Easy, which seemed backwards
	if( (random() < (0.2 + skill->value * 0.15) ) && !(self->spawnflags & SF_MONSTER_SPECIAL))
	{
		float	dist;
		float	time;

		dist = VectorLength (dir);
		time = dist/rocketSpeed;
		VectorMA(vec, time, self->enemy->velocity, vec);
		VectorSubtract(vec, start, dir);
	}

	VectorNormalize(dir);
	// paranoia, make sure we're not shooting a target right next to us
	trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT);
	if(trace.ent == self->enemy || trace.ent == world)
	{
		if(trace.fraction > 0.5 || (trace.ent && trace.ent->client))
			monster_fire_rocket (self, start, dir, 50, rocketSpeed, flash_number,
				(self->spawnflags & SF_MONSTER_SPECIAL ? self->enemy : NULL) );
	}
}